关于Java同步锁中await和signalAll的使用经验
来源:互联网 发布:淘宝吉他店铺推荐 编辑:程序博客网 时间:2024/05/16 19:30
当使用Lock来保证线程同步时,需使用Condition对象来使线程保持协调。Condition实例被绑定在一个Lock的对象上,使用Lock对象的方法newCondition()获取Condition的实例。Condition提供了下面三种方法,来协调不同线程的同步:
1、await():导致当前线程等待,直到其他线程调用该Condition的signal()或signalAll()方法唤醒该线程。
2、signal():唤醒在此Lock对象上等待的单个线程。
3、signalAll():唤醒在此Lock对象上等待的所有线程。
我在进行《疯狂Java讲义(精粹)第二版》多线程一章的一道习题的编程时遇到了使用了await()和signalAll()进行线程同步,却导致了死锁的问题。在网络搜寻了下,原因是我对await()方法理解有误导致。题目如下:写2个线程,其中一个线程打印1-52,另一个线程打印A-Z,打印顺序应该是12A34B56C……5152Z,需使用多线程通信的知识解决。
附上最终正确运行的代码,同时加上了开始时犯的错误的注释。
1、PrintTask
import java.util.ArrayList;import java.util.Iterator;import java.util.List;import java.util.concurrent.locks.Condition;import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReentrantLock;public class PrintTask<T> implements Runnable {private List<T> charList = new ArrayList<>();//需打印的队列。由于打印项目既包含字符也包含递增的数字,此处使用泛型private int period;//每次打印的个数private int priority;//优先级,即在多个队列中的打印次序private int total;//打印队列总数public static int sequence = 0;//当前打印的队列序号private static final Lock lock = new ReentrantLock();//由于需要锁定的sequence是类成员,创建一个static锁,保证该类不同线程实例能够感知到signalAll()private static final Condition condition = lock.newCondition();//类Condition成员//private final Lock lock = new ReentrantLock();----------->当不使用static定义Lock和Condition时,由于不同线程为不同的实例,相互之间//private final Condition condition = lock.newCondition();无法感知其他类发出的signalAll(),导致线程之间相互等待却无法得到响应public PrintTask(List<T> charList, int period, int priority, int total) {this.charList = charList;this.period = period;this.priority = priority;this.total = total;}public void run() {Iterator<T> iter = charList.iterator();while(true) {lock.lock();//锁定try {if (sequence % total == priority) {for (int i = 0; i < period; i++) {if(iter.hasNext()) {System.out.print(iter.next());}else {break;}}++sequence;condition.signalAll();//该类其他实例均能接受到该signalAll()方法}else {condition.await();//类成员condition的await()方法,告知类的所有实例均感知signalAll()}}catch (Exception ex) {ex.printStackTrace();}finally {lock.unlock();}}}}
2、主程序PrintAZ.java
import java.util.ArrayList;import java.util.List;public class PrintAZ {final static int TOTAL = 2;public static void main(String[] args) {//生成数字列表1-52List<Integer> numbers = new ArrayList<>();for (int i = 1; i <= 52; i++) {numbers.add(i);}//生成字母列表A-ZList<Character> chars = new ArrayList<>();for (char i = 'A'; i <= 'Z'; i++){chars.add(i);}//PrintTask(打印队列, 每次打印长度, 次序, 队列总数) PrintTask<Integer> task1 = new PrintTask<>(numbers, 2, 0, TOTAL);PrintTask<Character> task2 = new PrintTask<>(chars, 1, 1, TOTAL);new Thread(task1).start();new Thread(task2).start();}}
当定义Lock和Condition为实例成员变量时,运行结果如下:
12ALock和Condition为类成员时,运行结果如下:
12A34B56C78D910E1112F1314G1516H1718I1920J2122K2324L2526M2728N2930O3132P3334Q3536R3738S3940T4142U4344V4546W4748X4950Y5152Z
0 0
- 关于Java同步锁中await和signalAll的使用经验
- 黑马程序员——Java多线程—线程同步—Condition:await、signal、signalAll
- Java wait()和await() notify()和signal() notifyAll()和signalAll()了解和区别
- notify(),notifyAll()和signal(),signalAll()的异同
- .NET中使用异步Async和Await的代价
- 使用Promise和async-await实现的一个异步遍历+同步执行任务的实例
- MVC 5中Async和await使用
- .NET中async与await的使用
- 使用 Async 和 Await 的异步编程
- Java await和sleep的区别
- Java中关于同步和异步的区别
- 关于java的一些基础知识和经验
- java中同步、异步的使用和区别
- 关于多线程同步中使用的锁对象
- 关于async和await的一些误区实例详解
- java中路径关于/和.的使用
- MVC(七、action 中使用await和async)
- 关于Java中线程同步的问题
- C语言内存模型(内存组织方式)
- 回收站的重要文件删了怎么恢复
- 呼和浩特白光药水扑克
- hiho一下 第四十八周(拓扑排序的应用)48
- 简单内存泄漏检测方法 解决 Detected memory leaks! 问题
- 关于Java同步锁中await和signalAll的使用经验
- 【日常学习】【欧拉函数】codevs2296 仪仗队题解
- 撤销myeclipse误删的文件,更改应用名
- WebService到底是什么?
- Gradle学习系列之八——构建多个Project
- taskAffinity属性
- hrbust 1494 tarjan算法求割点模版
- Unable to find a java Virtual Machine ---- Oracle Developer
- oracle与excel 异曲同工之妙