838. 如何实现线程串⾏执⾏?

  1. 为了控制线程执⾏的顺序,如ThreadA->ThreadB->ThreadC->ThreadA循环执⾏三个线程,我们需要确定唤醒、等待的顺序。这时我们可以同时使⽤ Obj.wait()、Obj.notify()与synchronized(Obj)来实现这个⽬标。线程中持有上⼀个线程类的对象锁以及⾃⼰的锁,由于这种依赖关系,该线程执⾏需要等待上个对象释放锁,从⽽保证类线程执⾏的顺序。
  2. 通常情况下,wait是线程在获取对象锁后,主动释放对象锁,同时本线程休眠,直到有其它线程调⽤对象的notify()唤醒该线程,才能继续获取对象锁,并继续执⾏。⽽notify()则是对等待对象锁的线程的唤醒操作。但值得注意的是notify()调⽤后,并不是⻢上就释放对象锁,⽽是在相应的synchronized(){}语句块执⾏结束。释放对象锁后,JVM会在执⾏wait()等待对象锁的线程中随机选取⼀线程,赋予其对象锁,唤醒线程,继续执⾏。
1 public class ThreadSerialize {
2
3 public static void main(String[] args){
4 ThreadA threadA = new ThreadA();
5 ThreadB threadB = new ThreadB();
6 ThreadC threadC = new ThreadC();
7
8 threadA.setThreadC(threadC);
9 threadB.setThreadA(threadA);
10 threadC.setThreadB(threadB);
11
12 threadA.start();
13 threadB.start();
14 threadC.start();
15
16 while (true){
17 try {
18 Thread.currentThread().sleep(1000);
19 } catch (InterruptedException e) {
20 e.printStackTrace();
21 }
22 }
23 }
24 }
25
26 class ThreadA extends Thread{
27 private ThreadC threadC;
28 @Override
29 public void run() {
30 while (true){
31 synchronized (threadC){
32 synchronized (this){
33 System.out.println("I am ThreadA。。。");
34 this.notify();
35 }
36 try {
37 threadC.wait();
38 } catch (InterruptedException e) {
39 e.printStackTrace();
40 }
41 }
42 }
43
44 }
45
46 public void setThreadC(ThreadC threadC) {
47 this.threadC = threadC;
48 }
49 }
50 class ThreadB extends Thread{
51 private ThreadA threadA;
52 @Override
53 public void run() {
54 while (true){
55 synchronized (threadA){
56 synchronized (this){
57 System.out.println("I am ThreadB。。。");
58 this.notify();
59 }
60 try {
61 threadA.wait();
62 } catch (InterruptedException e) {
63 e.printStackTrace();
64 }
65 }
66 }
67
68 }
69
70 public void setThreadA(ThreadA threadA) {
71 this.threadA = threadA;
72 }
73 }
74 class ThreadC extends Thread{
75 private ThreadB threadB;
76 @Override
77 public void run() {
78 while (true){
79 synchronized (threadB){
80 synchronized (this){
81 System.out.println("I am ThreadC。。。");
82 this.notify();
83 }
84 try {
85 threadB.wait();
86 } catch (InterruptedException e) {
87 e.printStackTrace();
88 }
89 }
90 }
91
92 }
93
94 public void setThreadB(ThreadB threadB) {
95 this.threadB = threadB;
96 }
97 }
98
99