2.1 线程之间通信
线程之间概念:线程是操作系统中独立的个体,但这些个体如果不经过特殊的处理就不能成为一个整体,线程间的通信就成为整体的必用方式之一。当线程存在通信指挥,系统间的交互性会更强大,在提高cpu利用率的同时还会使开发人员对线程任务在处理的过程中进行有效的把握与监督。
使用wait/notify方法实现线程间的通信。(注意这个两个方法都是object的类的方法,换句话说java为所有的对象提供了这两个方法)
1、wait和notify必须配合synchronized关键字使用
2、Wait方法释放锁,notify方法不释放锁
示例:
/** * wait/notify的使用 * * 1、注意先启动t2再启动t1, t2先获得锁,进入等待状态,wait方法释放锁,如果t1先执行的话 * 因为t1不释放锁,这样t2就不会执行直到t1执行完毕 * * 2、线程停止不是实时性的,因为notify不释放锁,所以不会当notify后不会直接去执行t2. * * 3、弊端:不具备实时性通知 * 解决办法1:可以在notify后面加一个wait让当前线程释放锁去执行t2,然后等t2执行完了再唤醒t1。 * 解决办法2:可以使用CountDownLatch类 */ public class ListAdd01 { private volatile static List list = new ArrayList(); public void add() { list.add("ahdfi"); } public int size() { return list.size(); } public static void main(String[] args) { final Object lock = new Object(); final ListAdd01 list1 = new ListAdd01(); Thread t1 = new Thread(new Runnable() { @Override public void run() { // TODO Auto-generated method stub try { synchronized(lock) { for(int i = 0;i<10;i++) { list1.add(); System.out.println("当前线程: " + Thread.currentThread().getName() + "添加了一个元素.."); Thread.sleep(500); if(list1.size()==5) { System.out.println("已经发出通知.."); lock.notify(); //lock.wait(); } } } }catch(Exception e) { e.printStackTrace(); } } },"t1"); Thread t2 = new Thread(new Runnable() { @Override public void run() { // TODO Auto-generated method stub synchronized(lock) { if(list1.size()!=5) { try { lock.wait(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } //lock.notify(); System.out.println("当前线程收到通知:"+Thread.currentThread().getName()+" listsize=5 线程停止"); throw new RuntimeException();
} } },"t2"); t2.start(); t1.start(); } } |
运行结果: 当前线程: t1添加了一个元素.. 当前线程: t1添加了一个元素.. 当前线程: t1添加了一个元素.. 当前线程: t1添加了一个元素.. 当前线程: t1添加了一个元素.. 已经发出通知.. 当前线程: t1添加了一个元素.. 当前线程: t1添加了一个元素.. 当前线程: t1添加了一个元素.. 当前线程: t1添加了一个元素.. 当前线程: t1添加了一个元素.. 当前线程收到通知:t2 listsize=5 线程停止 Exception in thread "t2" java.lang.RuntimeException at edu.sdut.thread02.ListAdd01$2.run(ListAdd01.java:71) at java.lang.Thread.run(Unknown Source) |
使用CountDownLatch类解决实时性
import java.util.concurrent.CountDownLatch; /** * CountDownLatch实现实时性通知 * 实时通知打印 * @author Vision_TXG * */ public class TestCountLatch { private volatile static List list = new ArrayList(); public void add() { list.add("ahdfi"); } public int size() { return list.size(); } public static void main(String[] args) { //final Object lock = new Object(); final TestCountLatch list1 = new TestCountLatch(); /** * 使用CountDownLatch */ final CountDownLatch countDownLatch = new CountDownLatch(1); Thread t1 = new Thread(new Runnable() {
@Override public void run() { // TODO Auto-generated method stub try { //synchronized(lock) { for(int i = 0;i<10;i++) { list1.add(); System.out.println("当前线程: " + Thread.currentThread().getName() + "添加了一个元素.."); Thread.sleep(500); if(list1.size()==5) { System.out.println("已经发出通知.."); countDownLatch.countDown(); //lock.notify(); //lock.wait(); } } //} }catch(Exception e) { e.printStackTrace(); } } },"t1"); Thread t2 = new Thread(new Runnable() {
@Override public void run() { // TODO Auto-generated method stub //synchronized(lock) { if(list1.size()!=5) { try { countDownLatch.await(); //lock.wait(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } //lock.notify(); System.out.println("当前线程收到通知:"+Thread.currentThread().getName()+" listsize=5 线程停止"); throw new RuntimeException();
//} } },"t2"); t2.start(); t1.start(); } } |
运行结果: 当前线程: t1添加了一个元素.. 当前线程: t1添加了一个元素.. 当前线程: t1添加了一个元素.. 当前线程: t1添加了一个元素.. 当前线程: t1添加了一个元素.. 已经发出通知.. 当前线程: t1添加了一个元素.. 当前线程收到通知:t2 listsize=5 线程停止 Exception in thread "t2" java.lang.RuntimeException at edu.sdut.thread02.TestCountLatch$2.run(TestCountLatch.java:75) at java.lang.Thread.run(Unknown Source) 当前线程: t1添加了一个元素.. 当前线程: t1添加了一个元素.. 当前线程: t1添加了一个元素.. 当前线程: t1添加了一个元素.. |