多线程的经典ABC
多线程理解的比较好的方法是ABC方法,此处我仅以代码为例进行说明:
1)如下为编辑的线程类
package threadAll; public class TwoRunnable implements Runnable { private String name; private Object prev; private Object self; public TwoRunnable(String name, Object prev, Object self) { this.name = name; this.prev = prev; this.self = self; } @Override public void run() { int count = 10; while (count > 0) { synchronized (prev) { synchronized (self) { System.out.print(name); count--; self.notify(); } try { prev.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } } } }
2)以下为测试线程的类:
package threadAll;
public class TestMain {
public static void main(String[] args)throws Exception {
Object a = new Object();
Object b = new Object();
Object c = new Object();
TwoRunnable pa = new TwoRunnable("A", c, a); //拥有c和a两个锁,然后执行完Synchronized{}中的语句以后,会释放a和c
TwoRunnable pb = new TwoRunnable("B", a, b);
TwoRunnable pc = new TwoRunnable("C", b, c);
new Thread(pa).start();
Thread.sleep(1000); //确保按顺序A、B、C执行
new Thread(pb).start();
Thread.sleep(1000);
new Thread(pc).start();
Thread.sleep(1000);
}
}
3)对代码的详细说明
=======================第一轮的简单分析==============================
理论分析:首先开启第一个线程,第一个线程之后,第一个线程就会将c,a 两个对象进行锁定
等其执行过后,通过prev.wait()[其中 prev 为c对象]第一个线程就处于等待状态
然后执行self.notify[其中self是对象a],表示将之前通过a.wait()的阻塞线程处于就绪
同时释放c,a两个对象的对象锁
之后开启第二个线程,第二个开启后就会对a,b两个对象进行上锁,等其执行之后,
通过prev.wait()[其中prev是a对象]第二个线程执行之后就处于等待状态,
然后执行self.notify[其中self是b],表示将之前通过b.wait()的阻塞线程的状态改为就绪
同时释放a,b的对象锁
之后开启第三个线程,第三个线程开启后就会对b,c两个对象进行上锁,等其执行之后,
通过prev.wait()[其中prev是b对象]第二个线程执行之后就处于等待状态,
然后执行self.notify[其中self是c],表示将之前通过c.wait()的阻塞线程的状态改为就绪
同时释放a,b的对象锁
======================第二轮的分析==================================
由于第一轮执行过后,现在的第一个线程的状态通过第一轮中的第三个线程执行的c.notify之后
变为了就绪,线程2,3仍处于阻塞状态,所以第一个线程就会执行。
第一个线程就会通过self.notify[其中self是对象a],表示将之前通过a.wait()的阻塞线程处于就绪
这样第一个线程通过执行c.wait()处于阻塞,第三个线程仍处于阻塞,第二个线程则处于就绪,开始执行
第二个线程执行与之前相同
本篇代码转自https://www.cnblogs.com/GarfieldEr007/p/5746362.html