线程锁ReentrantLock和Condition的使用
来源:互联网 发布:淘宝怎么查宝贝降权 编辑:程序博客网 时间:2024/06/05 10:20
我们通过一个实际的例子来解释Condition的用法:
我们要打印1到9这9个数字,由A线程先打印1,2,3,然后由B线程打印4,5,6,然后再由A线程打印7,8,9. 这道题有很多种解法,现在我们使用Condition来做这道题(使用Object的wait,notify方法的解法在这里)。
package cn.outofmemory.locks;import java.util.concurrent.locks.Condition;import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReentrantLock;public class App {static class NumberWrapper {public int value = 1;}public static void main(String[] args) {//初始化可重入锁final Lock lock = new ReentrantLock();//第一个条件当屏幕上输出到3final Condition reachThreeCondition = lock.newCondition();//第二个条件当屏幕上输出到6final Condition reachSixCondition = lock.newCondition();//NumberWrapper只是为了封装一个数字,一边可以将数字对象共享,并可以设置为final//注意这里不要用Integer, Integer 是不可变对象final NumberWrapper num = new NumberWrapper();//初始化A线程Thread threadA = new Thread(new Runnable() {@Overridepublic void run() {//需要先获得锁lock.lock();try {System.out.println("threadA start write");//A线程先输出前3个数while (num.value <= 3) {System.out.println(num.value);num.value++;}//输出到3时要signal,告诉B线程可以开始了reachThreeCondition.signal();} finally {lock.unlock();}lock.lock();try {//等待输出6的条件reachSixCondition.await();System.out.println("threadA start write");//输出剩余数字while (num.value <= 9) {System.out.println(num.value);num.value++;}} catch (InterruptedException e) {e.printStackTrace();} finally {lock.unlock();}}});Thread threadB = new Thread(new Runnable() {@Overridepublic void run() {try {lock.lock();while (num.value <= 3) {//等待3输出完毕的信号reachThreeCondition.await();}} catch (InterruptedException e) {e.printStackTrace();} finally {lock.unlock();}try {lock.lock();//已经收到信号,开始输出4,5,6System.out.println("threadB start write");while (num.value <= 6) {System.out.println(num.value);num.value++;}//4,5,6输出完毕,告诉A线程6输出完了reachSixCondition.signal();} finally {lock.unlock();}}});//启动两个线程threadB.start();threadA.start();}}
上述代码中有完整的注释,请参考注释,理解Condition的用法。
基本思路就是首先要A线程先写1,2,3,这时候B线程应该等待reachThredCondition信号,而当A线程写完3之后就通过signal告诉B线程“我写到3了,该你了”,这时候A线程要等嗲reachSixCondition信号,同时B线程得到通知,开始写4,5,6,写完4,5,6之后B线程通知A线程reachSixCondition条件成立了,这时候A线程就开始写剩下的7,8,9了。
为了更好的理解Condition的用法,我们再看下java官方提供的例子:
package locks;import java.util.Random;import java.util.concurrent.locks.Condition;import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReentrantLock;public class AppOfficial {/** * BoundedBuffer 是一个定长100的集合,当集合中没有元素时,take方法需要等待,直到有元素时才返回元素 * 当其中的元素数达到最大值时,要等待直到元素被take之后才执行put的操作 * @author yukaizhao * */static class BoundedBuffer {final Lock lock = new ReentrantLock();final Condition notFull = lock.newCondition();final Condition notEmpty = lock.newCondition();final Object[] items = new Object[100];int putptr, takeptr, count;public void put(Object x) throws InterruptedException {System .out.println("put wait lock");lock.lock();System.out.println("put get lock");try {while (count == items.length) {System.out.println("buffer full, please wait");notFull.await();}items[putptr] = x;if (++putptr == items.length)putptr = 0;++count;notEmpty.signal();} finally {lock.unlock();}}public Object take() throws InterruptedException {System.out.println("take wait lock");lock.lock();System.out.println("take get lock");try {while (count == 0) {System.out.println("no elements, please wait");notEmpty.await();}Object x = items[takeptr];if (++takeptr == items.length)takeptr = 0;--count;notFull.signal();return x;} finally {lock.unlock();}}}public static void main(String[] args) {final BoundedBuffer boundedBuffer = new BoundedBuffer();Thread t1 = new Thread(new Runnable() {@Overridepublic void run() {System.out.println("t1 run");for (int i=0;i<1000;i++) {try {System.out.println("putting..");boundedBuffer.put(Integer.valueOf(i));} catch (InterruptedException e) {e.printStackTrace();}}}}) ;Thread t2 = new Thread(new Runnable() {@Overridepublic void run() {for (int i=0;i<1000;i++) {try {Object val = boundedBuffer.take();System.out.println(val);} catch (InterruptedException e) {e.printStackTrace();}}}}) ;t1.start();t2.start();}}
这个示例中BoundedBuffer是一个固定长度的集合,这个在其put操作时,如果发现长度已经达到最大长度,那么会等待notFull信号,如果得到notFull信号会像集合中添加元素,并发出notEmpty的信号,而在其take方法中如果发现集合长度为空,那么会等待notEmpty的信号,同时如果拿到一个元素,那么会发出notFull的信号。
0 0
- 线程锁ReentrantLock和Condition的使用
- ReentrantLock 和 Condition的使用
- ReentrantLock类和Condition类的使用
- 多线程锁的使用(ReentrantLock/Condition/ReentrantReadWriteLock)
- ReentrantLock使用Condition实现通知部分线程
- ReentrantLock使用Condition实现通知部分线程
- Java多线程11:ReentrantLock的使用和Condition
- 记一次使用ReentrantLock和Condition并发锁,对数据库批处理代码的优化
- ReentrantLock Condition使用详解
- java线程之Condition、ReentrantLock
- 利用ReentrantLock的Condition实现线程之间的通信
- 4.1.5ReentrantLock与Condition选择性的唤醒线程
- 使用ReentrantLock和Condition实现生产者消费者模型
- ReentrantLock与Condition结合使用
- join(),ReentrantLock结合Condition的await(),signal()的使用
- JAVA多线程-Lock的使用(一)-ReentrantLock与Condition
- Java多线程编程4--Lock的使用--重入锁(ReentrantLock)、Condition
- Java并发编程 之 Condition与ReentrantLock的使用
- 51nod 1247 可能的路径 (最大公约数变形)
- Android 拖拉控件遇到的问题
- 【FOJ2207 11月月赛C】【DFS栈性质应用 离线处理】以撒的结合 从x到y路径上的第k个点 询问众多
- Poj 1734 Sightseeing trip floyd最小环
- RTTI、虚函数和虚基类的开销分析及使用指导
- 线程锁ReentrantLock和Condition的使用
- [Python标准库]string——文本常量和模板
- 从大数据菜鸟走上大师的历程
- 90Subsets II
- IntelliJ IDEA快捷键note
- ubuntu12.04下搭建android开发环境
- Handler 使用学习总结
- 数据库与MATLAB链接http://blog.sina.com.cn/s/blog_9d0b00a401012spy.html
- AJAX 在IE 下提交到后台乱码,但ff不会