线程间通信,就要联想到Object的wait、notify、notifyAll和Lock.new Condition()的await、signal、signalAll。
【1】需求一,三个线程顺序打印ABC,每个线程打印十次,ABC分别为线程名字
效果如下:
A A A A A A A A A A //BC依次排列
使用synchronized、wait、notifyAll实例代码如下:
public class TestSwapThread { public static void main(String[] args){ //创建三把锁 final Object obj1 = new Object(); final Object obj2 = new Object(); final Object obj3 = new Object(); SwapThread swapThread = new SwapThread(obj1,obj2); SwapThread swapThread2 = new SwapThread(obj3,obj1); SwapThread swapThread3 = new SwapThread(obj2,obj3); swapThread.setName("A"); swapThread.start(); //这里来保证次序 try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } swapThread2.setName("B"); swapThread2.start(); try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } swapThread3.setName("C"); swapThread3.start(); } } class SwapThread extends Thread{ private Object obj1 = null; private Object obj2 = null; public SwapThread(Object obj1,Object obj2){ this.obj1 = obj1; this.obj2 = obj2; } @Override public void run() { synchronized (obj1){ System.out.println(Thread.currentThread().getName()+"准备进入第二层"); synchronized (obj2){ for (int i=0;i<10;i++){ System.out.println(Thread.currentThread().getName()+" : "+i); } //nofityAll并不会释放锁,但是同步代码块执行完会自动释放锁 obj2.notifyAll(); }//这里释放内存锁 //nofityAll并不会释放锁,但是同步代码块执行完会自动释放锁 obj1.notifyAll(); System.out.println(Thread.currentThread().getName()+" : end"); }//这里释放外层锁 } }
使用lock实例如下
public class TestSwapThread3 { public static void main(String[] args){ //这里也可作为swapThread3 构造参数传入 //Lock lock = new ReentrantLock(); SwapThread3 swapThread3 = new SwapThread3(); new Thread(swapThread3,"A").start(); new Thread(swapThread3,"B").start(); new Thread(swapThread3,"C").start(); } } class SwapThread3 implements Runnable{ //共享数据--同一把锁 ReentrantLock private Lock lock =new ReentrantLock() ; @Override public void run() { //加锁 lock.lock(); try { int count =0; while (count<10){ System.out.println(Thread.currentThread().getName()+" : "+count ); count++; } }finally { //释放锁 lock.unlock(); } } }
程序执行结果如下:
其实lock加锁/释放锁和顺序打印本质是保存线程执行的次序,严格意义从理论来讲,第二种方式在某些情况下是不太正确的。
【2】需求二,三个线程轮流打印ABC,每个线程打印十次,ABC分别为线程名字
效果如下:
A B C //....
这时,就对线程通信要求高了。
使用synchronized、wait、notifyAll实例代码如下:
public class TestSwapThread4 { public static void main(String[] args){ final Object obj1 = new Object(); final Object obj2 = new Object(); final Object obj3 = new Object(); SwapThread4 swapThread = new SwapThread4(obj1,obj2); SwapThread4 swapThread2 = new SwapThread4(obj2,obj3); SwapThread4 swapThread3 = new SwapThread4(obj3,obj1); swapThread.setName("A"); swapThread.start(); swapThread2.setName("B"); swapThread2.start(); swapThread3.setName("C"); swapThread3.start(); } } class SwapThread4 extends Thread{ private Object obj1 = null; private Object obj2 = null; public SwapThread4(Object obj1,Object obj2){ this.obj1 = obj1; this.obj2 = obj2; } @Override public void run() { for (int i=0;i<10;i++){ synchronized (obj1){ synchronized (obj2){ System.out.println(Thread.currentThread().getName()+" : "+i); //notifyAll并不会释放锁,代码块结束后释放锁 obj2.notifyAll(); } try { //避免程序不能正常结束 if (i==9){ obj1.notifyAll(); }else{ //wait方法将会释放锁标志,进入阻塞状态,等到唤醒 obj1.wait(); } } catch (InterruptedException e) { e.printStackTrace(); } } } } }
测试结果如下:
使用Lock+Condition实例如下:
public class TestSwapThread2 { public static void main(String[] args){ Lock lock = new ReentrantLock(); Condition conditionA = lock.newCondition(); Condition conditionB = lock.newCondition(); Condition conditionC = lock.newCondition(); SwapThread2 swapThread = new SwapThread2(lock,conditionA,conditionB); SwapThread2 swapThread2 = new SwapThread2(lock,conditionB,conditionC); SwapThread2 swapThread3 = new SwapThread2(lock,conditionC,conditionA); swapThread.setName("A"); swapThread.start(); swapThread2.setName("B"); swapThread2.start(); swapThread3.setName("C"); swapThread3.start(); } } class SwapThread2 extends Thread{ private Lock lock ; private Condition condition1; private Condition condition2 ; public SwapThread2(Lock lock,Condition condition1,Condition condition2){ this.lock = lock; this.condition1=condition1; this.condition2=condition2; } @Override public void run() { //加锁 lock.lock(); try { int count =0; while (count<10){ //唤醒等待condition2的线程 condition2.signal(); System.out.println(Thread.currentThread().getName()+" : "+count ); count++; if (count==10){ //避免程序不能结束 condition1.signalAll(); }else{ try { //当前线程进入阻塞,等到condition1被唤醒 condition1.await(); } catch (InterruptedException e) { e.printStackTrace(); } } } }finally { lock.unlock(); } } }