一个锁可能关联了一个或多个条件。这些条件可以在Condition接口中声名。



使用这些条件的目的是去控制一个锁并且可以检查一个条件是true或false,如果为false,则暂停直到

另一个线程来唤醒它。



Condition接口提供了这样一个机制 去暂定一个线程和唤醒一个暂停中的线程。

本例中继续拿生产者-消费者问题举例。

FileMock.java
package com.dylan.thread.ch2.c07.utils;

/**
* This class simulates a text file. It creates a defined number
* of random lines to process them sequentially.
*
*/
public class FileMock { /**
* Content of the simulate file
*/
private String content[];
/**
* Number of the line we are processing
*/
private int index; /**
* Constructor of the class. Generate the random data of the file
* @param size: Number of lines in the simulate file
* @param length: Length of the lines
*/
public FileMock(int size, int length){
content=new String[size];
for (int i=0; i<size; i++){
StringBuilder buffer=new StringBuilder(length);
for (int j=0; j<length; j++){
int indice=(int)Math.random()*255;
buffer.append((char)indice);
}
content[i]=buffer.toString();
}
index=0;
} /**
* Returns true if the file has more lines to process or false if not
* @return true if the file has more lines to process or false if not
*/
public boolean hasMoreLines(){
return index<content.length;
} /**
* Returns the next line of the simulate file or null if there aren't more lines
* @return
*/
public String getLine(){
if (this.hasMoreLines()) {
System.out.println("Mock: "+(content.length-index));
return content[index++];
}
return null;
} }
Buffer.java
package com.dylan.thread.ch2.c07.task;

import java.util.LinkedList;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock; /**
* This class implements a buffer to stores the simulate file lines between the
* producer and the consumers
*
*/
public class Buffer { /**
* The buffer
*/
private LinkedList<String> buffer; /**
* Size of the buffer
*/
private int maxSize; /**
* Lock to control the access to the buffer
*/
private ReentrantLock lock; /**
* Conditions to control that the buffer has lines and has empty space
*/
private Condition lines;
private Condition space; /**
* Attribute to control where are pending lines in the buffer
*/
private boolean pendingLines; /**
* Constructor of the class. Initialize all the objects
*
* @param maxSize
* The size of the buffer
*/
public Buffer(int maxSize) {
this.maxSize = maxSize;
buffer = new LinkedList<>();
lock = new ReentrantLock();
lines = lock.newCondition();
space = lock.newCondition();
pendingLines = true;
} /**
* Insert a line in the buffer
*
* @param line
* line to insert in the buffer
*/
public void insert(String line) {
lock.lock();
try {
while (buffer.size() == maxSize) {
space.await();
}
buffer.offer(line);
System.out.printf("%s: Inserted Line: %d\n", Thread.currentThread()
.getName(), buffer.size());
lines.signalAll();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
} /**
* Returns a line from the buffer
*
* @return a line from the buffer
*/
public String get() {
String line=null;
lock.lock();
try {
while ((buffer.size() == 0) &&(hasPendingLines())) {
lines.await();
} if (hasPendingLines()) {
line = buffer.poll();
System.out.printf("%s: Line Readed: %d\n",Thread.currentThread().getName(),buffer.size());
space.signalAll();
}
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
return line;
} /**
* Establish the value of the variable
*
* @param pendingLines
*/
public void setPendingLines(boolean pendingLines) {
this.pendingLines = pendingLines;
} /**
* Returns the value of the variable
*
* @return the value of the variable
*/
public boolean hasPendingLines() {
return pendingLines || buffer.size() > 0;
} }
Producer.java
package com.dylan.thread.ch2.c07.task;

import com.dylan.thread.ch2.c07.utils.FileMock;

/**
* This class gets lines from the simulate file and stores them in the
* buffer, if there is space in it.
*
*/
public class Producer implements Runnable { /**
* Simulated File
*/
private FileMock mock; /**
* Buffer
*/
private Buffer buffer; /**
* Constructor of the class. Initialize the objects
* @param mock Simulated file
* @param buffer Buffer
*/
public Producer (FileMock mock, Buffer buffer){
this.mock=mock;
this.buffer=buffer;
} /**
* Core method of the producer. While are pending lines in the
* simulated file, reads one and try to store it in the buffer.
*/
@Override
public void run() {
buffer.setPendingLines(true);
while (mock.hasMoreLines()){
String line=mock.getLine();
buffer.insert(line);
}
buffer.setPendingLines(false);
} }
Consumer.java
package com.dylan.thread.ch2.c07.task;

import java.util.Random;

/**
* This class reads line from the buffer and process it
*
*/
public class Consumer implements Runnable { /**
* The buffer
*/
private Buffer buffer; /**
* Constructor of the class. Initialize the buffer
* @param buffer
*/
public Consumer (Buffer buffer) {
this.buffer=buffer;
} /**
* Core method of the consumer. While there are pending lines in the
* buffer, try to read one.
*/
@Override
public void run() {
while (buffer.hasPendingLines()) {
String line=buffer.get();
processLine(line);
}
} /**
* Method that simulates the processing of a line. Waits 10 milliseconds
* @param line
*/
private void processLine(String line) {
try {
Random random=new Random();
Thread.sleep(random.nextInt(100));
} catch (InterruptedException e) {
e.printStackTrace();
}
} }
Main.java
package com.dylan.thread.ch2.c07.core;

import com.dylan.thread.ch2.c07.task.Buffer;
import com.dylan.thread.ch2.c07.task.Consumer;
import com.dylan.thread.ch2.c07.task.Producer;
import com.dylan.thread.ch2.c07.utils.FileMock; /**
* Main class of the example
*
*/
public class Main { /**
* Main method of the example
* @param args
*/
public static void main(String[] args) {
/**
* Creates a simulated file with 100 lines
*/
FileMock mock=new FileMock(101, 10); /**
* Creates a buffer with a maximum of 20 lines
*/
Buffer buffer=new Buffer(20); /**
* Creates a producer and a thread to run it
*/
Producer producer=new Producer(mock, buffer);
Thread threadProducer=new Thread(producer,"Producer"); /**
* Creates three consumers and threads to run them
*/
Consumer consumers[]=new Consumer[3];
Thread threadConsumers[]=new Thread[3]; for (int i=0; i<3; i++){
consumers[i]=new Consumer(buffer);
threadConsumers[i]=new Thread(consumers[i],"Consumer "+i);
} /**
* Strats the producer and the consumers
*/
threadProducer.start();
for (int i=0; i<3; i++){
threadConsumers[i].start();
}
} }

运行结果:

Mock: 101
Producer: Inserted Line: 1
Mock: 100
Producer: Inserted Line: 2
Mock: 99
Producer: Inserted Line: 3
Mock: 98
Producer: Inserted Line: 4
Mock: 97
Producer: Inserted Line: 5
Mock: 96
Producer: Inserted Line: 6
Mock: 95
Producer: Inserted Line: 7
Mock: 94
Producer: Inserted Line: 8
Mock: 93
Producer: Inserted Line: 9
Mock: 92
Producer: Inserted Line: 10
Mock: 91
Producer: Inserted Line: 11
Mock: 90
Producer: Inserted Line: 12
Mock: 89
Producer: Inserted Line: 13
Mock: 88
Producer: Inserted Line: 14
Mock: 87
Producer: Inserted Line: 15
Mock: 86
Producer: Inserted Line: 16
Mock: 85
Producer: Inserted Line: 17
Mock: 84
Producer: Inserted Line: 18
Mock: 83
Producer: Inserted Line: 19
Mock: 82
Producer: Inserted Line: 20
Mock: 81
Consumer 0: Line Readed: 19
Consumer 0: Line Readed: 18
Consumer 1: Line Readed: 17

...

Mock: 2
Consumer 1: Line Readed: 19
Consumer 2: Line Readed: 18
Consumer 2: Line Readed: 17
Producer: Inserted Line: 18
Mock: 1
Producer: Inserted Line: 19
Consumer 0: Line Readed: 18
Consumer 2: Line Readed: 17
Consumer 1: Line Readed: 16
Consumer 0: Line Readed: 15
Consumer 2: Line Readed: 14
Consumer 0: Line Readed: 13
Consumer 2: Line Readed: 12
Consumer 1: Line Readed: 11
Consumer 0: Line Readed: 10
Consumer 0: Line Readed: 9
Consumer 2: Line Readed: 8
Consumer 0: Line Readed: 7
Consumer 2: Line Readed: 6
Consumer 1: Line Readed: 5
Consumer 1: Line Readed: 4
Consumer 0: Line Readed: 3
Consumer 2: Line Readed: 2
Consumer 0: Line Readed: 1
Consumer 1: Line Readed: 0

Java并发编程实例--19.在一个锁中使用多个条件的更多相关文章

  1. Java并发编程实战 03互斥锁 解决原子性问题

    文章系列 Java并发编程实战 01并发编程的Bug源头 Java并发编程实战 02Java如何解决可见性和有序性问题 摘要 在上一篇文章02Java如何解决可见性和有序性问题当中,我们解决了可见性和 ...

  2. Java并发编程:线程和锁的使用与解析

    线程的使用  新建线程 新建一个线程有两种方法:继承Thread类,然后重写run方法:实现Runnable接口,然后实现run方法.实际上Thread类也是实现的Runnable接口,再加上类只能单 ...

  3. java并发编程系列原理篇--JDK中的通信工具类Semaphore

    前言 java多线程之间进行通信时,JDK主要提供了以下几种通信工具类.主要有Semaphore.CountDownLatch.CyclicBarrier.exchanger.Phaser这几个通讯类 ...

  4. Java并发编程:Lock(锁)

    一.synchronized的缺陷 synchronized是java中的一个关键字,也就是说是Java语言内置的特性.那么为什么会出现Lock呢? 在上面一篇文章中,我们了解到如果一个代码块被syn ...

  5. Java并发编程(05):悲观锁和乐观锁机制

    本文源码:GitHub·点这里 || GitEE·点这里 一.资源和加锁 1.场景描述 多线程并发访问同一个资源问题,假如线程A获取变量之后修改变量值,线程C在此时也获取变量值并且修改,两个线程同时并 ...

  6. 【Java并发编程】:多线程环境中安全使用集合API

    在集合API中,最初设计的Vector和Hashtable是多线程安全的.例如:对于Vector来说,用来添加和删除元素的方法是同步的.如果只有一个线程与Vector的实例交互,那么,要求获取和释放对 ...

  7. Java并发编程实例(synchronized)

    此处用一个小程序来说明一下,逻辑是一个计数器(int i):主要的逻辑功能是,如果同步监视了资源i,则不输出i的值,但如果没有添加关键字synchronized,因为是两个线程并发执行,所以会输出i的 ...

  8. Java并发编程-可重入锁

    可重入锁,也叫做递归锁,指的是同一线程 外层函数获得锁之后 ,内层递归函数仍可以获取该锁而不受影响.在JAVA环境下 ReentrantLock 和synchronized 都是 可重入锁. publ ...

  9. 【Java并发编程】4、JDK7中TransferQueue的使用以及TransferQueue与SynchronousQueue的差别

    转自:http://blog.csdn.net/aitangyong/article/details/46472643 JDK7对JDK5中的J.U.C并发工具进行了增强,其中之一就是新增了Trans ...

  10. Java并发编程之显式锁机制

    我们之前介绍过synchronized关键字实现程序的原子性操作,它的内部也是一种加锁和解锁机制,是一种声明式的编程方式,我们只需要对方法或者代码块进行声明,Java内部帮我们在调用方法之前和结束时加 ...

随机推荐

  1. ZHS16GBK字符集下面Oracle数据库varchar与nvarchar的验证

    ZHS16GBK字符集下面Oracle数据库varchar与nvarchar的验证 背景 周末分析了 SQLServer mysql等数据库 想着继续分析一下oracle数据库 这边oracle使用的 ...

  2. [转帖]Nginx中absolute_redirect、port_in_redirect配置简述

    一.背景: 我们在访问nginx代理下的项目前端页面时,经常会有访问链接最末尾带不带'/'的问题,当我们访问http://xxxx/home时,如果匹配不到location,会自动加上端口port以及 ...

  3. Harbor的逻辑备份与学习

    Harbor的逻辑备份与学习 背景 一直想处理一下一个有网络冲突的Harbor镜像服务器 但是因为网络层自己水平一直是不是非常自信 加上Harbor容器使用的compose的玩法, 自己不敢直接处理. ...

  4. [转帖]Tiup 常用运维操作命令干货

    https://zhuanlan.zhihu.com/p/356031031 **导读**> 作者:杨漆> 16年关系型数据库管理,从oracle 9i .10g.11g.12c到Mysq ...

  5. [转帖]金仓数据库KingbaseES V8R6 索引膨胀

    索引膨胀 对于索引,随着业务不断的增删改,会造成膨胀,尤其Btree索引,也会涉及索引分裂.合并等,导致索引访问效率降低.维护成本增加.另外,索引页的复用与HEAP PAGE不一样,因为索引的内容是有 ...

  6. Cosmic云星瀚的简单学习-测试用户创建

    摘要 上一个学习文档里面总结了: 修改domain的url之后就可以重启服务然后登录了. 今天中午创建了一个业务用户,发现还挺麻烦的 因为可能短信服务有问题, 所以我这边需要有改数据库表的需求. 这里 ...

  7. Python控制微信,实现聊天机器人

    自从微信禁止网页版登陆之后,itchat 库实现的功能也就都不能用了,那现在 Python 还能操作微信吗?答案是:可以! 在Github上有一个项目叫<WeChatPYAPI>可以使用 ...

  8. 领域知识图谱的医生推荐系统:利用BERT+CRF+BiLSTM的医疗实体识别,建立医学知识图谱,建立知识问答系统

    领域知识图谱的医生推荐系统:利用BERT+CRF+BiLSTM的医疗实体识别,建立医学知识图谱,建立知识问答系统 本项目主要实现了疾病自诊和医生推荐两个功能并构建了医生服务指标评价体系.疾病自诊主要通 ...

  9. 【二】强化学习之Parl基础命令--PaddlePaddlle及PARL框架{飞桨}

    相关文章: [一]飞桨paddle[GPU.CPU]安装以及环境配置+python入门教学 [二]-Parl基础命令 [三]-Notebook.&pdb.ipdb 调试 [四]-强化学习入门简 ...

  10. 强化学习基础篇[3]:DQN、Actor-Critic详细讲解

    强化学习基础篇[3]:DQN.Actor-Critic详细讲解 1.DQN详解 1.1 DQN网络概述及其创新点 在之前的内容中,我们讲解了Q-learning和Sarsa算法.在这两个算法中,需要用 ...