不管是一个condition 两个condition 三个condition 都需要一个标志未来判定
案例1的 flag
案例2的 count ==100 count ==0
案例3的 number =1
1 Lock和Condition简介:
Lock 替代 synchronized
比传统线程模型synchronized更加面向对象,
能够适应 "hand-over-hand" 或 "chain locking":获取节点 A 的锁,然后再获取节点 B 的锁,然后释放 A 并获取 C,然后释放 B 并获取 D,这种灵活的锁机制;
Condition 功能类似于object.wait() 和 notify()
Condition的特点:
以前的方式只能有一个等待队列,在实际应用时可能需要多个,比如读和写。
为了这个灵活性,创建多个condition,
互斥保证在某个时刻只有一个线程访问临界区(lock自己完成),
等待队列负责保存被阻塞的线程(condition完成)。
2 lock+condition案例一,生产者消费者代码(单队列 只需要一个condition):
package thread; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; /** * * @author zm * 执行结果: 第 0 次执行B 第 1 次执行A 第 1 次执行B 第 2 次执行A 第 2 次执行B 第 3 次执行A 第 3 次执行B 第 4 次执行A 第 4 次执行B 第 5 次执行A 第 5 次执行B 第 6 次执行A 第 6 次执行B 第 7 次执行A 第 7 次执行B 第 8 次执行A 第 8 次执行B 第 9 次执行A 第 9 次执行B * * * 为什么需要使用condition呢?简单一句话,lock更灵活。以前的方式只能有一个等待队列,在实际应用时可能需要多个,比如读和写。为了这个灵活性,lock将同步互斥控制和等待队列分离开来, * 互斥保证在某个时刻只有一个线程访问临界区(lock自己完成),等待队列负责保存被阻塞的线程(condition完成)。 * * 案例1:我生产一个面包,就通知顾客来拿 * condition能够实现实际业务中 多等待队列交互模式, 传统 wait() notify()只能实现一个等待队列; * 下面案例是使用 conditon实现 一个等待队列模式 取代 传统 wait() notify()的写法( 生产者-消费者, 我生产一个面包,就通知顾客来拿, 只有一个队列) * * * 案例2: 两队人,一队不停像100个篮子生产面包,一队不停从篮子拿走面包(阻塞队列) * * 如果是我不停的生产面包放在篮子里,我不管消费者拿面包, notfull队列(篮子还没存放满面包队列 有自己独自的wait nodify) * 而消费者不停的去从篮子里拿面包,而不管生产者生产了多少, notempty队列(篮子面包还没空队列 有自己独自的wait nodify) * 那么这就是两个队列, * notfull队列, 只管像篮子里放面包,当100个篮子满的时,放面包动作处于等待 * notempty队列,只管从篮子里拿面包,当100个篮子空的时,存面包动作处于等待 * 此时需要使用同一个lock的两个condition来实现第二个案例 * */ public class CommunicateWithConditionThread { // A 执行一次 B 执行一次 一共执行20次 public static void main(String[] args) { final Out out = new Out(); // out对象就是同一个门栓 new Thread(new Runnable() { @Override public void run() { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } for(int i=0; i<10; i++){ out.printA(i); } } }).start(); new Thread(new Runnable() { @Override public void run() { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } for(int i=0; i<10; i++){ out.printB(i); } } }).start(); } } class Out { // public boolean flag = true; Lock lock = new ReentrantLock(); Condition conditon = lock.newCondition(); // 使用一个conditon, 模拟一组等待队列 public void printA(int i){ lock.lock(); try{ while(!flag){// 当flag = false时,线程执行此业务方法时等待 try { conditon.await();// 门栓等待 } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println("第 " + i + " 次执行A,生产了面包"); // 否则直接执行业务方法 flag = false; // 更改标志位 conditon.signal(); // 使用方法 不要使用错了 }finally{ lock.unlock(); } } public void printB(int j){ lock.lock(); try{ while(flag) {// 当flag = true时, 线程执行此业务方法时等待 try { conditon.await();// 门栓等待 } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println("第 " + j + " 次执行B,消费了面包"); flag = true; // 更改标志位 conditon.signal(); // }finally{ lock.unlock(); } } }
3 lock+condition案例二,多队列等待代码(阻塞队列 需要两个condition):
* 案例2: 两队人,一对不停像100个篮子生产面包,一对不停从篮子拿走面包(阻塞队列) * * 如果是我不停的生产面包放在篮子里,我不管消费者拿面包, notfull队列(篮子还没存放满面包队列 有自己独自的wait nodify) * 而消费者不停的去从篮子里拿面包,而不管生产者生产了多少, notempty队列(篮子面包还没空队列 有自己独自的wait nodify) * 那么这就是两个队列, * notfull队列, 只管像篮子里放面包,当100个篮子满的时,放面包动作处于等待 * notempty队列,只管从篮子里拿面包,当100个篮子空的时,存面包动作处于等待 * 此时需要使用同一个lock的两个condition来实现第二个案例 * 注意: count表示当前面包真实个数(生产一个 同时下个线程拿走一个 那么count = 0) * items: 存放面包篮子 * putptr, 生产面包后 存放在篮子的角标, * takeptr,取走面包时,面包所在篮子的角标 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 { lock.lock(); // 生产面包上锁 try { while (count == items.length) // 当生产队列并发大到突然生产了100个面包时,生产队列等待 notFull.await(); // 否则执行生产面包操作, 不断向数组下一个单元格内放新面包 items[putptr] = x; if (++putptr == items.length) putptr = 0;// 当存放的面包到达数组最后位置时,篮子存放面包位置又从0开始 ++count; // 记录面包个数 notEmpty.signal();// 生产了面包,就立即通知消费队列去取走面包 } finally { lock.unlock();// 生产面包完成 解锁 让下个生产执行 } } public Object take() throws InterruptedException { lock.lock();// 取面包上锁 try { while (count == 0) // 当消费队列消费并发过大,或者刚开始没生产出面包时,消费队列等待 notEmpty.await(); Object x = items[takeptr]; if (++takeptr == items.length) takeptr = 0;// 当取走面包到篮子最后一个位置时,重置,再从篮子最开始位置取面包 --count;// 记录面包个数 取走一次面包 个数减一 notFull.signal(); // 取走面包, 立即通知生产队列生产面包 return x; } finally { lock.unlock(); // 取面包完成 解锁 让下个取面包动作执行 } } }
3 lock+condition案例三,(三队列):
扩展: 产生三个线程 A -->B --> C ---> A 这里需要三个condition
package thread; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; /** * 三个队列下: * A循环打印5次, B循环打印5次 , C循环打印5次, A执行完后通知B,B 执行完后通知C, C执行完后通知A, 这种形式循环5次 * @author zm * */ public class ThreeConditionCommunication { /** * @param args */ public static void main(String[] args) { final Business business = new Business(); new Thread( new Runnable() { @Override public void run() { for(int i=1;i<=5;i++){ business.sub1(i); } } } ).start(); new Thread( new Runnable() { @Override public void run() { for(int i=1;i<=5;i++){ business.sub2(i); } } } ).start(); new Thread( new Runnable() { @Override public void run() { for(int i=1;i<=5;i++){ business.sub3(i); } } } ).start(); } static class Business { Lock lock = new ReentrantLock(); Condition condition1 = lock.newCondition(); Condition condition2 = lock.newCondition(); Condition condition3 = lock.newCondition(); private int num = 1; public void sub1(int i){ lock.lock(); try{ while(num != 1){ try { condition1.await(); } catch (Exception e) { e.printStackTrace(); } } for(int j=1;j<=5;j++){ System.out.println("sub1 thread sequence of " + j + ",loop of " + i); } num = 2; condition2.signal(); }finally{ lock.unlock(); } } public void sub2(int i){ lock.lock(); try{ while(num != 2){ try { condition2.await(); } catch (Exception e) { e.printStackTrace(); } } for(int j=1;j<=5;j++){ System.out.println("sub2 thread sequence of " + j + ",loop of " + i); } num = 3; condition3.signal(); }finally{ lock.unlock(); } } public void sub3(int i){ lock.lock(); try{ while(num != 3){ try { condition3.await(); } catch (Exception e) { e.printStackTrace(); } } for(int j=1;j<=5;j++){ System.out.println("sub3 thread sequence of " + j + ",loop of " + i); } num = 1; condition1.signal(); }finally{ lock.unlock(); } } } }
脑图:
相关推荐
根据提供的标题、描述、标签及部分内容,我们可以了解到这篇文章主要提供了JDK 1.5/5.0/1.6三个版本的中文文档下载链接。这些文档以CHM格式提供,分别对应不同版本的JDK,并且是经过完整翻译的中文版。下面我们将...
此外,JDK 1.5还引入了新的编译器——Client Compiler和Server Compiler,根据不同的场景选择合适的编译策略,提升代码执行速度。 总结,JDK 1.5的64位Windows版本为Java开发者提供了在64位系统上开发和运行Java...
JDK1.5是Java的一个重要版本,它在2004年9月30日正式发布,也被称为Java 5.0。这个版本引入了大量的新特性,对Java平台进行了重大改进,提升了开发效率和性能。 首先,JDK1.5引入了类型安全的枚举(enum),这是对...
### JDK 1.5、1.6 和 1.7 的新特性详解 #### JDK 1.5 新特性概述 1. **自动装箱与拆箱:** - 自动装箱指的是将基本数据类型自动转换为对应的包装类对象的过程。 - 例如:`Integer iObj = 3;` 这里将整型 `3` ...
3. **安装JDK**:使用RPM命令来安装JDK1.5: ``` sudo rpm -ivh jdk-1_5_0_22-linux-amd64.rpm ``` 4. **配置环境变量**:安装完成后,需要将JDK的路径添加到系统的`PATH`环境变量中。打开或创建`~/.bashrc`或`/...
在JDK1.5中,开发者可以在方法签名中使用省略号(...)表示可变参数。这允许方法接受任意数量的相同类型的参数,如: ```java public void printNumbers(int... nums) { // 代码块 } ``` 这个方法可以接收一个或多...
泛型是JDK1.5最重要的特性之一,它允许在类、接口和方法声明中使用类型参数,以实现数据类型的参数化。泛型提高了代码的类型安全性和可读性,减少了类型转换的需要,并允许编译器检查类型错误。 2. **自动装箱与...
此外,JDK1.5还引入了变长参数(Varargs)功能,允许在方法声明中使用三个点(...)表示可变长度的参数列表。这使得创建接受任意数量相同类型参数的方法变得更加简单。 在类型系统方面,JDK1.5引入了增强的for循环...
1. **泛型(Generics)**:泛型是JDK 1.5最显著的新特性之一,它允许在类、接口和方法中使用类型参数,从而提高了代码的类型安全性和重用性。这减少了在运行时可能遇到的ClassCastException。 2. **自动装箱/拆箱...
jdk1.5.exe jdk1.5 jdk1.5下载
绝版jdk1.5,非常不错的资源。用起来很好。是 Java语言对Bean类属性、事件的一种缺省处理方法。例如类A中有属性name,那我们可以通过getName,setName来得到其值或者设置新 的值。通过getName/setName来访问name属性,...
前几天上传过这个资源,因为是在jdk1.6上开发的, 测试了一下在jdk1.5上不能用, 今天重新用jdk1.5编译了一下, 这个是可以支持jdk1.5+的 将 pu-xlscommon-1.0.0.jar 添加到工程的 /lib 目录下 用法在附件中 XlsTest....
这个压缩包包含了三个不同版本的JDK:JDK 1.5、JDK 1.6和JDK 1.8,其中1.5和1.6是早期版本,而1.8是最流行且广泛使用的版本之一。 **JDK 1.5(也称为Java 5.0)** JDK 1.5在2004年发布,引入了许多重要的新特性,如...
标题中的"window JDK1.5 32位 绿色免安装版"指的是适用于Windows操作系统的32位版本的JDK 1.5,它是一个便携式版本,无需正式安装即可使用。这种绿色免安装版通常是为了方便开发者在不同机器间快速切换工作环境,或...
在"IBM_jdk1.5_Guide.pdf"这个文档中,很可能是IBM JDK 1.5的官方指南或开发者手册,它将详细阐述如何安装、配置和使用IBM JDK 1.5,以及如何在AIX环境下进行Java开发。而"www.pudn.com.txt"可能是下载资源的来源...
JDK1.5 全平台安装包下载 百度网盘资源 jdk-1_5_0_22-linux-amd64-rpm.bin jdk-1_5_0_22-linux-amd64.bin jdk-1_5_0_22-linux-i586-rpm.bin jdk-1_5_0_22-linux-i586.bin jdk-1_5_0_22-solaris-amd64...
测试可用的linux版jdk1.5,jdk-1_5_0_19-linux-i586-rpm.bin
**JDK1.5**,又称为Java Development Kit的第5个主要版本,标志着Java语言的一个重大里程碑。这个版本引入了一系列创新性特性和改进,极大地提升了开发效率和代码的可读性,为Java编程带来了全新的体验。以下是JDK...
JDK1.5,也被称为Java SE 5.0,是一个重要的版本,它引入了许多创新特性,对于Java的发展历程具有深远的影响。 在JDK1.5中,最重要的变化之一是引入了泛型。泛型允许在定义类、接口和方法时指定类型参数,从而增强...
在使用JDK 1.5进行开发时,开发者可以享受到这些新特性的便利,提高代码质量和开发效率。然而,由于该版本已经比较老,可能不支持现代的Java特性,对于新项目,推荐使用更新的JDK版本。对于旧项目,迁移至更高版本的...