volatile实现
package com.jeff.base.conn008; import java.util.ArrayList; import java.util.List; /** * 定义t1和t2两个线程: * t1线程往list中加入元素 * t2线程发现list元素个数为5时抛出异常,停止t2线程 * * @author jeff * @param args */ public class ListAdd1 { private volatile static List list = new ArrayList(); public void add(){ list.add("bjsxt"); } public int size(){ return list.size(); } public static void main(String[] args) { final ListAdd1 list1 = new ListAdd1(); Thread t1 = new Thread(new Runnable() { @Override public void run() { try { for(int i = 0; i <10; i++){ list1.add(); System.out.println("当前线程:" + Thread.currentThread().getName() + "添加了一个元素.."); Thread.sleep(500); } } catch (InterruptedException e) { e.printStackTrace(); } } }, "t1"); Thread t2 = new Thread(new Runnable() { @Override public void run() { while(true){ if(list1.size() == 5){ System.out.println("当前线程收到通知:" + Thread.currentThread().getName() + " list size = 5 线程停止.."); throw new RuntimeException(); } } } }, "t2"); t1.start(); t2.start(); } }
打印结果:
当前线程:t1添加了一个元素.. 当前线程:t1添加了一个元素.. 当前线程:t1添加了一个元素.. 当前线程:t1添加了一个元素.. 当前线程:t1添加了一个元素.. 当前线程收到通知:t2 list size = 5 线程停止.. Exception in thread "t2" java.lang.RuntimeException at com.jeff.base.conn008.ListAdd1$2.run(ListAdd1.java:50) at java.lang.Thread.run(Thread.java:722) 当前线程:t1添加了一个元素.. 当前线程:t1添加了一个元素.. 当前线程:t1添加了一个元素.. 当前线程:t1添加了一个元素.. 当前线程:t1添加了一个元素..
wait和notify实现
package com.jeff.base.conn008; import java.util.ArrayList; import java.util.List; import java.util.Queue; import java.util.concurrent.CountDownLatch; import java.util.concurrent.LinkedBlockingDeque; import java.util.concurrent.LinkedBlockingQueue; /** * wait notfiy 方法,wait释放锁,notfiy不释放锁 * @author jeff * */ public class ListAdd2 { private volatile static List list = new ArrayList(); public void add(){ list.add("bjsxt"); } public int size(){ return list.size(); } public static void main(String[] args) { final ListAdd2 list2 = new ListAdd2(); // 1 实例化出来一个 lock // 当使用wait 和 notify 的时候 , 一定要配合着synchronized关键字去使用 final Object lock = new Object(); // final CountDownLatch countDownLatch = new CountDownLatch(1); Thread t1 = new Thread(new Runnable() { @Override public void run() { try { synchronized (lock) { for(int i = 0; i <10; i++){ list2.add(); System.out.println("当前线程:" + Thread.currentThread().getName() + "添加了一个元素.."); Thread.sleep(500); if(list2.size() == 5){ System.out.println("已经发出通知.."); // countDownLatch.countDown(); lock.notify(); } } } } catch (InterruptedException e) { e.printStackTrace(); } } }, "t1"); Thread t2 = new Thread(new Runnable() { @Override public void run() { synchronized (lock) { if(list2.size() != 5){ try { System.out.println("t2进入..."); lock.wait(); // countDownLatch.await(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println("当前线程:" + Thread.currentThread().getName() + "收到通知线程停止.."); throw new RuntimeException(); } } }, "t2"); t2.start(); t1.start(); } }
打印结果:
t2进入... 当前线程:t1添加了一个元素.. 当前线程:t1添加了一个元素.. 当前线程:t1添加了一个元素.. 当前线程:t1添加了一个元素.. 当前线程:t1添加了一个元素.. 已经发出通知.. 当前线程:t1添加了一个元素.. 当前线程:t1添加了一个元素.. 当前线程:t1添加了一个元素.. 当前线程:t1添加了一个元素.. 当前线程:t1添加了一个元素.. 当前线程:t2收到通知线程停止.. Exception in thread "t2" java.lang.RuntimeException at com.jeff.base.conn008.ListAdd2$2.run(ListAdd2.java:72) at java.lang.Thread.run(Thread.java:722)
我们发现以后结果并不是实时的,分析下执行过程:
t2线程先执行,执行到await方法时释放锁,然后t1获得锁,当t1添加5个元素后,调用notify方法唤醒t2线程,但是notify方法并不释放锁,所以t2线程此时并不能得到锁,直到t1线程添加完10个元素以后释放锁,t2线程await才不再阻塞,打印“收到通知线程停止”。
CountDownLatch方式
package com.jeff.base.conn008; import java.util.ArrayList; import java.util.List; import java.util.Queue; import java.util.concurrent.CountDownLatch; import java.util.concurrent.LinkedBlockingDeque; import java.util.concurrent.LinkedBlockingQueue; /** * wait notfiy 方法,wait释放锁,notfiy不释放锁 * @author jeff * */ public class ListAdd2 { private volatile static List list = new ArrayList(); public void add(){ list.add("bjsxt"); } public int size(){ return list.size(); } public static void main(String[] args) { final ListAdd2 list2 = new ListAdd2(); // 1 实例化出来一个 lock // 当使用wait 和 notify 的时候 , 一定要配合着synchronized关键字去使用 // final Object lock = new Object(); final CountDownLatch countDownLatch = new CountDownLatch(1); Thread t1 = new Thread(new Runnable() { @Override public void run() { try { // synchronized (lock) { for(int i = 0; i <10; i++){ list2.add(); System.out.println("当前线程:" + Thread.currentThread().getName() + "添加了一个元素.."); Thread.sleep(500); if(list2.size() == 5){ System.out.println("已经发出通知.."); countDownLatch.countDown(); // lock.notify(); } } // } } catch (InterruptedException e) { e.printStackTrace(); } } }, "t1"); Thread t2 = new Thread(new Runnable() { @Override public void run() { // synchronized (lock) { if(list2.size() != 5){ try { System.out.println("t2进入..."); // lock.wait(); countDownLatch.await(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println("当前线程:" + Thread.currentThread().getName() + "收到通知线程停止.."); throw new RuntimeException(); // } } }, "t2"); t2.start(); t1.start(); } }
打印结果:
t2进入... 当前线程:t1添加了一个元素.. 当前线程:t1添加了一个元素.. 当前线程:t1添加了一个元素.. 当前线程:t1添加了一个元素.. 当前线程:t1添加了一个元素.. 已经发出通知.. Exception in thread "t2" java.lang.RuntimeException at com.jeff.base.conn008.ListAdd2$2.run(ListAdd2.java:72) at java.lang.Thread.run(Thread.java:722) 当前线程:t1添加了一个元素.. 当前线程:t2收到通知线程停止.. 当前线程:t1添加了一个元素.. 当前线程:t1添加了一个元素.. 当前线程:t1添加了一个元素.. 当前线程:t1添加了一个元素..
执行countDown方法后,计数器减去1,变为0,t2线程停止阻塞实时开始执行...