从屌丝到架构师的飞越(多线程篇)-线程通信
一.介绍
由于多线程共享地址空间和数据空间,所以多个线程间的通信是一个线程的数据可以直接提供给其他线程使用,而不必通过操作系统(也就是内核的调度)。
不同的线程执行不同的任务,如果之些任务有某种联系,线程之间必须能够通信,协调完成工作。
线程与线程之间不是相互独立的个体,它们彼此之间需要相互通信和协作,最典型的例子就是生产者-消费者问题。本文首先介绍 wait/notify 机制,并对实现该机制synchronized+wait-notify模进行详细剖析,以作为线程间通信与协作的基础。
二.知识点介绍
1、线程通信的方法
2、生产者与消费者模型
三.上课对应视频的说明文档
1、线程通信的方法
(1)wait() //这个方法可以使线程一直等待,直到其他线程调用notify(或notifyAll)将其唤醒。
(2)notify() //唤醒一个等待同一个管程锁的线程,如果同一管程锁下有多个线程处于睡眠等待状态,则随机地挑出一个等待线程将其唤醒。
(3)notifyAll()//唤醒所有等待同一管程锁的线程,这些唤醒后的线程同样也要拥有管程才能继续执行。
这三个方法必须在synchronized代码块中调用,否则会出现IllegalMonitorStateException异常。
2、生产者与消费者模型

当仓库满时,生产者需要等待队列有空间才能继续往里面放入商品,而在等待的期间内,生产者必须释放对临界资源(即队列)的占用权。因为生产者如果不释放对临界资源的占用权,那么消费者就无法消费队列中的商品,就不会让队列有空间,那么生产者就会一直无限等待下去。因此,一般情况下,当队列满时,会让生产者交出对临界资源的占用权,并进入挂起状态。然后等待消费者消费了商品,然后消费者通知生产者队列有空间了。同样地,当队列空时,消费者也必须等待,等待生产者通知它队列中有商品了。
注意:
(1) 根据仓库的状态来判断执行生产者还是消费者
(2) 通过同步和线程通信的方法来协调线程执行
案例:
Q3.java类
class Q3{
private String name="衬衣";
private String sex="1000";
boolean bFull=false;//控制线程间的通信
public synchronized void put(String name,String sex) throws Exception{
if(bFull) wait();//控制线程间的通信
this.name=name;
try{
Thread.sleep(10);
}catch(Exception e){
System.out.println(e.getMessage());
}
this.sex=sex;
bFull=true;//控制线程间的通信
notify();//控制线程间的通信
}
public synchronized void get() throws Exception{
if(!bFull) wait();//控制线程间的通信
System.out.println(name+"----->"+sex);
bFull=false;//控制线程间的通信
notify();//控制线程间的通信
}
}
Producer3.java类
class Producer3 implements Runnable{
Q3 q=null;
public Producer3(Q3 q){
this.q=q;
}
public void run(){
int i=0;
while(true){
//编写往数据存储空间放入数据的代码
try {
if(i==0){
q.put("裤子","8000");
}else{
q.put("衬衣","1000");
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} i=(i+1)%2;
}
}
}
Consumer3.java类
class Consumer3 implements Runnable{
Q3 q=null;
public Consumer3(Q3 q){
this.q=q;
}
public void run(){
while(true){
//编写从数据存储空间中读取数据的代码
try {
q.get();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
ThreadCommunation3.java类
public class ThreadCommunation3{
public static void main(String args[]){
Q3 q=new Q3();
new Thread(new Producer3(q)).start();
new Thread(new Consumer3(q)).start();
}
}