什么是多线程的通信?
多线程对同一共享资源的不同操作。
wait()
wait方法将当前的线程挂起,并释放出锁资源。wait方法属于Object类中。
此方法应始终在循环中使用:
synchronized (obj) { while (<condition does not hold>) obj.wait(); ... // Perform action appropriate to condition }
此方法只应由作为此对象监视器的所有者的线程来调用。
package com.cn.test.thread; public class TestWait extends Thread{ Object obj = new Object(); @Override public void run() { for (int i = 0; i < 10; i++) { System.out.println("running start"); try { obj.wait(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println("running over"); } } public static void main(String[] args) { TestWait testWait = new TestWait(); testWait.start(); } }
此方法必须同sychnorized同时使用,不使用sychnorized直接调用此方法发生异常:
running start Exception in thread "Thread-0" java.lang.IllegalMonitorStateException at java.lang.Object.wait(Native Method) at java.lang.Object.wait(Object.java:502) at com.cn.test.thread.TestWait.run(TestWait.java:12)
package com.cn.test.thread; public class TestWait extends Thread{ Object obj = new Object(); @Override public void run() { for (int i = 0; i < 10; i++) { System.out.println("running start"); synchronized (obj) { try { obj.wait(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println("running over"); } } } public static void main(String[] args) { TestWait testWait = new TestWait(); testWait.start(); } }
运行结果:线程一直处于阻塞的状态
running start
obj.wait(long time);
该方法挂去time长的时间,时间已过,线程又处于竞争cpu的资源中、
此方法导致当前线程(称之为 T)将其自身放置在对象的等待集中,然后放弃此对象上的所有同步要求。出于线程调度目的,在发生以下四种情况之一前,线程 T 被禁用,且处于休眠状态:
- 其他某个线程调用此对象的 notify 方法,并且线程 T 碰巧被任选为被唤醒的线程。
- 其他某个线程调用此对象的 notifyAll 方法。
- 其他某个线程中断线程 T。
- 大约已经到达指定的实际时间。但是,如果 timeout 为零,则不考虑实际时间,在获得通知前该线程将一直等待。
notify()唤醒在此对象监视器上等待的单个线程。如果所有线程都在此对象上等待,则会选择唤醒其中一个线程。选择是任意性的,并在对实现做出决定时发生。线程通过调用其中一个 wait
方法,在对象的监视器上等待。notifyAll()唤醒当前等待的所有的线程。
notifyAll()唤醒在此对象监视器上等待的所有线程。线程通过调用其中一个 wait
方法,在对象的监视器上等待。
例子: 生产者消费者,生产者写入数据,消费者进行消费数据
package com.cn.test.thread; public class Resource { public String name; public String color; public boolean sychFlag = true; //同步标识 }
package com.cn.test.thread; public class Customer extends Thread{ private Resource res; Customer(Resource res) { this.res = res; } @Override public void run() { while (true) { synchronized (res) { if (!res.sychFlag) { // 消费者进行消费 System.out.println("name=" + res.name + "color =" + res.color); // 消费者消费完毕 res.sychFlag = true; // 阻塞当前的线程 res.notifyAll(); } else { try { res.wait(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } } }
package com.cn.test.thread; public class Producer extends Thread{ private Resource res; Producer(Resource res) { this.res = res; } @Override public void run() { /** * 同步标识为true生产者开始进行生产 * 消费者进行等待 */ int count = 0; while (true) { synchronized (res) { if (res.sychFlag) { // 生产者进行生产 if (count % 2 == 0) { res.name = "张三"; res.color = "blue"; } else { res.name = "尤其"; res.color = "red"; } count++; res.sychFlag = false; // 写完之后唤醒当前的线程 res.notifyAll(); } else { // 阻塞当前线程,并且释放锁的资源 try { res.wait(); Thread.sleep(100); System.out.println("我被挂起了"); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } } }
package com.cn.test.thread; public class TestMain { public static void main(String[] args) { Resource res = new Resource(); Producer p = new Producer(res); Producer p2 = new Producer(res); Customer c = new Customer(res); Customer c1 = new Customer(res); c.start(); // c1.start(); p.start(); // p2.start(); } }