Java多线程wait,notify以及同步锁的运用实例
来源:互联网 发布:文字翻译语音软件 编辑:程序博客网 时间:2024/05/29 04:35
一次性开多个线程打印10次ABC的小Demo,如何保证线程执行的有序性,以下面这个Demo来做说明:
package com.lyt.usermanage.test;public class MyThreadTest5 implements Runnable { private String name; private Object lastThread; private Object self; public MyThreadTest5(String name,Object lastThread,Object self){ this.name = name; this.lastThread = lastThread; this.self = self; } @Override public void run() { int count = 10; while(count>0){ synchronized(lastThread){ synchronized(self){ System.out.print(name); count --; /*唤醒在等待该对象同步锁的线程(只唤醒一个,如果有多个在等待),注意的是在调用此方法的时候, 并不能确切的唤醒某一个等待状态的线程,而是由JVM确定唤醒哪个线程,而且不是按优先级。 调用任意对象的notify()方法则导致因调用该对象的 wait()方法而阻塞的线程中随机选择的一个解除阻塞(但要等到获得锁后才真正可执行)。*/ self.notify(); } try { //调用任意对象的 wait() 方法导致该线程阻塞,该线程不可继续执行,并且该对象上的锁被释放。 lastThread.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } } }}
package com.lyt.usermanage.test;public class ThreadTest { public static void main(String[] args) throws InterruptedException { System.out.println(Thread.currentThread().getName()+"主线程运行开始!"); Object a = new Object(); Object b = new Object(); Object c = new Object(); MyThreadTest5 pa = new MyThreadTest5("A", c, a); MyThreadTest5 pb = new MyThreadTest5("B", a, b); MyThreadTest5 pc = new MyThreadTest5("C", b, c); new Thread(pa).start(); Thread.sleep(100); //确保按顺序A、B、C执行 new Thread(pb).start(); Thread.sleep(100); new Thread(pc).start(); Thread.sleep(100); }}
先来解释一下其整体思路,从大的方向上来讲,该问题为三线程间的同步唤醒操作,
主要的目的就是ThreadA->ThreadB->ThreadC->ThreadA循环执行三个线程。为了控制线程执行的顺序,
那么就必须要确定唤醒、等待的顺序,所以每一个线程必须同时持有两个对象锁,才能继续执行。
一个对象锁是prev,就是前一个线程所持有的对象锁。还有一个就是自身对象锁。
主要的思想就是,为了控制执行的顺序,必须要先持有prev锁,也就前一个线程要释放自身对象锁,再去申请自身对象锁,
两者兼备时打印,之后首先调用self.notify()释放自身对象锁,唤醒下一个等待线程,再调用prev.wait()释放prev对象锁,
终止当前线程,等待循环结束后再次被唤醒。运行上述代码,可以发现三个线程循环打印ABC,共10次。程序运行的主要过程就是A线程最先运行,
持有C,A对象锁,后释放A,C锁,唤醒B。线程B等待A锁,再申请B锁,后打印B,再释放B,A锁,唤醒C,线程C等待B锁,再申请C锁,后打印C,再释放C,B锁,唤醒A。
看起来似乎没什么问题,但如果你仔细想一下,就会发现有问题,就是初始条件,三个线程按照A,B,C的顺序来启动,按照前面的思考,A唤醒B,B唤醒C,C再唤醒A。
但是这种假设依赖于JVM中线程调度、执行的顺序。
具体流程:
我们看到A B C三个线程共用三个锁对象a b c,由于在主线程加了休眠,那么三个线程的执行顺序就有了ABC的保障;A线程进来run方法后打印A,然后唤醒需要a对象同步锁的线程并释放持有的a对象锁,这个时候只有B线程在申请a锁,于是B线程被唤醒,然后A线程调用wait方法进入阻塞状态并释放c锁;B线程进行和A线程一样的步骤,进来后打印B然后释放b锁并唤醒等待b对象的线程,也就是C线程,然后调用wait方法进入阻塞状态并释放a对象;C线程重复上面的操作,唤醒了等待c锁对象的A线程,又是一个循环,因为new Thread(pa).start(); 方法里面不是公用的一个对象,所以各个线程都要跑10次,达到我们的需求10次ABC的输出。
个人理解是这样,如果有不足请大家多留言改进,技术只有交流才能深刻。
- Java多线程wait,notify以及同步锁的运用实例
- 多线程同步 synchronized 以及wait notify notigyAll的总结
- java多线程同步设计wait/notify机制
- java多线程同步设计wait/notify机制
- java多线程同步设计wait/notify机制
- [转]java多线程同步,wait和notify
- java多线程synchronized,notify,wait应用实例
- java 多线程 wait() 以及 notify() 简析
- [java多线程]多线程同步(二)——wait, notify, notifyAll, join以及sleep
- Java基础(高级)——多线程的理解和Synchronized实例,以及线程间通信,wait,notify等方法
- java多线程运用notify和wait(修改)
- Java多线程wait/notify
- Java【多线程知识总结(8)】线程通信,wait()与notify()的运用
- Java【多线程知识总结(8)】线程通信,wait()与notify()的运用
- java 中的 wait/notify 同步锁机制
- JAVA多线程的理解wait、notify、notifyAll
- Java多线程的wait()和notify()例子
- Java多线程的wait()和notify()例子
- python中list的拷贝与numpy的array的拷贝
- OpenJudge 1.7 21:单词替换
- 实验五—【项目三】成绩
- 汉若塔问题(递归与栈两种方法)
- ARP协议和RARP协议的使用场景
- Java多线程wait,notify以及同步锁的运用实例
- fastJson 详解
- java中this关键字的作用
- Oracle数据库服务器CPU持续100%之等待事件asynch descriptor resize
- Redis相关参数设置总结
- TCP/IP
- LeetCode题解–131. Palindrome Partitioning
- Web Api 的 路由机制
- 百度地图