多线程循环打印ABC
主要是利用线程的wait()和notify()来实现
public class MyThread implements Runnable { private String name; private Object prev; private Object mine; private MyThread(String name,Object prev,Object mine){ this.name = name; this.prev = prev; this.mine = mine; } @Override public void run() { int count = 10; while(count > 0){ synchronized (prev) { synchronized (mine) { System.out.println(name); count--; mine.notify(); } try { prev.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } } } public static void main(String[] args) { Object a = new Object(); Object b = new Object(); Object c = new Object(); MyThread pa = new MyThread("A", c, a); MyThread pb = new MyThread("B", a, b); MyThread pc = new MyThread("C", b, c); new Thread(pa).start(); new Thread(pb).start(); new Thread(pc).start(); } }
整理下程序的思路:因3个线程要按照顺序打印ABC,那么应该是ThreadA->ThreadB->ThreadC->ThreadA如此循环,当运行ThreadA时,prev对象是c,mine对象是a,打印A,然后唤醒线程a,最后让当前线程c等待,则ThreadA进入等待(注意此时调用的prev.wait()虽然让线程进入了等待,但同时也释放了对象的锁,其他线程可以访问此同步方法)。ThreadB的prev对象是a,mine对象是b,打印B;而ThreadC的prev对象是b,mine对象是c;其实这种方式不一定能完全保证是ABC的顺序输出,因为看程序,B线程在等待a对象的锁,获取a的锁才能继续向下进行,而C线程在如果抢先运行的话,b的锁是不需要等待的,则直接等待a的锁,在ThreadA运行完毕释放锁后,若C线程率先获取a的锁的话,那么打印顺序就会遭到改变。所以若要让线程A、B、C按照顺序执行的话,一定要让3个线程按照顺序执行。更改程序为:
1 public class MyThread implements Runnable { 2 private String name; 3 private Object prev; 4 private Object mine; 5 6 private MyThread(String name,Object prev,Object mine){ 7 this.name = name; 8 this.prev = prev; 9 this.mine = mine; 10 } 11 12 13 @Override 14 public void run() { 15 int count = 10; 16 while(count > 0){ 17 synchronized (prev) { 18 synchronized (mine) { 19 System.out.println(name); 20 count--; 21 try { 22 Thread.sleep(1); 23 } catch (InterruptedException e) { 24 e.printStackTrace(); 25 } 26 mine.notify(); 27 } 28 29 try { 30 prev.wait(); 31 } catch (InterruptedException e) { 32 e.printStackTrace(); 33 } 34 35 } 36 } 37 38 } 39 40 41 public static void main(String[] args) { 42 Object a = new Object(); 43 Object b = new Object(); 44 Object c = new Object(); 45 MyThread pa = new MyThread("A", c, a); 46 MyThread pb = new MyThread("B", a, b); 47 MyThread pc = new MyThread("C", b, c); 48 try { 49 new Thread(pa).start(); 50 Thread.sleep(10); 51 new Thread(pb).start(); 52 Thread.sleep(10); 53 new Thread(pc).start(); 54 } catch (InterruptedException e) { 55 e.printStackTrace(); 56 } 57 58 } 59 60 }
这样就能真正的实现,第一遍运行顺序为ThreadA打印A,然后ThreadA等待->ThreadB打印B,然后B等待->ThreadC打印C,然后C等待并唤醒A;以此循环打印了。
文章思路不是很清晰,主要还是学习别人写的东西,转化成自己能够理解的语言。努力学习中!