引子
线程通讯表示线程间可以进行数据交流, 最简单的实现方式就是使用共享资源, 看下面代码:
//共享资源
public class Resource {
private int resource;
public synchronized int getResource(){
return resource;
}
public synchronized void setResource(){
resource++;
}
}
public class App {
public static void main(String[] args) {
//2线程公用一个资源
final Resource resource = new Resource();
new Thread(new Runnable() {
public void run() {
resource.getResource();
}
}, "t1").start();
new Thread(new Runnable() {
public void run() {
resource.setResource();
}
}, "t2").start();
}
}
分析:
上面代码定义一个resource类,线程t1, t2 共享操作, 实现t1,t2线程的共享.但是, 单纯使用这种方式, 实操性不强, 无法做到真正的通讯. 这个可以类比日常生活中的通讯, 比如:打电话. A拨号找B, 会响铃通知B电话来了.通话结束后, B挂断电话, A就知道通话结束.如果A电话没来,B先守着.而线程通讯更多指向于AB线程间能具有通知,等待的功能. 那如何做到? 答案是: JDK的wait/notify方法
java.lang.Object类下面有3个方法: wait(), notify()和notifyAll() 完成线程通讯.其操作原理非常简单, 一个线程调用任意一个对象的wait方法, 该线程马上进入非运行状态, 当且仅当其他线程调用同一个对象的notify或者notifyAll方法, 这个线程才有机会转换成等待状态或者可运行状态. 这里强调下, 线程想要调用对象的wait/notify/notifyAll方法, 就必须持有对象的锁.换句话说, 在调用wait跟notify方法时, 必须使用synchronized.
那这个与线程通讯有毛关系? 看下经典例子: 生产者与消费者
需求: 一个包子店, 只有一个面包师, 一个蒸笼.蒸笼只能放满10个包子, 当满10个包子时,面包师可以休息.如果包子卖完了,就得开始弄包子.而顾客一次买一个包子, 当包子就只能等啦.
public class BaoZiShop {
//包子个数
private int baoziNum = 0;
public int getBaoziNum() {
return baoziNum;
}
public void setBaoziNum(int baoziNum) {
this.baoziNum = baoziNum;
}
}
//面包师
public class Baker implements Runnable {
private BaoZiShop shop;
public Baker(BaoZiShop shop) {
this.shop = shop;
}
public void run() {
while (true){
synchronized (shop){
if(shop.getBaoziNum() >= 10){
try {
System.out.println("面包师:" + Thread.currentThread().getName()
+ "发现包子满了,果断休息...");
shop.wait();
} catch (InterruptedException e) {
e.printStackTrace();