手头有两个人(也就是两个类),一个做存操作,一个做取操作,并且只有当存完或者取完方可进行令一个操作。以此达到循环输出的存取操作。
第一步:先写测试生产者类与消费者类 和 线程操作Msg类
//生产者
public class Product implements Runnable{
private Msg msg = null; //线程操作对象
public Product (Msg msg){
super();
this.msg = msg;
}
@override
public void run(){
for(int i=0;i<10;i++){
if(i%2==0){
try{
this.msg.set("男","胡明明");
}catch{
e.printStackTrace();
}else{
this.msg.set("女","肖体秀");
}
}
}
}
}
//消费者
public class Consumer implements Runnable{
private Msg msg = null;
public Consumer (Msg msg){
super();
this.msg = msg;
}
@override
public void run(){
for(int i=0;i<10;i++){
try{
this.msg.get();
}catch{
e.printStackTrance();
}
}
}
}
//线程操作Msg类
public class Msg{
private String title;
private String content;
private boolearn flag = true;//true:生产者可以生产,不能取 false:消费者可以取,生产者不能生产
//多个线程访问统一资源。要考虑到数据是否同步的问题,当线程进入睡眠或者等待其它线程会趁虚而入,所以在方法加上一把锁
public synchrnoized void set (String title,String content){
if(this.flag == false){//存线程等待
System.out.println(Thread.currentThread().getName()+ "进入等待")
super.wait();
}
this.title = title;
this.content = content;
this.flag = false;//存完成,改变标识
System.out.println(Thread.currentThread.getNmae() + "睡眠,并唤醒睡眠或者等待的线程")
super.notify();//唤醒第一个等待的线程(取)
}
public synchrnoized void get(){
if(this.flag == true){//取等待
super.wait();
}
System.out.println(Thread.currentThread().getName() + this.title +"-----" + this.content)
this.flag = false;//存完成,改变标识
super.notify();//唤醒第一个等待的线程(存)
}
public static void main(String[] args){
Msg msg = new Msg();//实例化对象
new Thread(msg,"存线程1")。start();
new Thread(msg,"存线程2")。start();
//new Thread(msg,"取线程")。start();
}
}
/**
*实际上这个也很好理解,假设有两个线程,存线程和取线程(两个不同的操作类)被cpu调用,进入队列,假
*设存线程先被执行**那么,先走for循环第次存(同步,别的线程进不来)胡明明,当准备走第1次时,再次进
*行存的操作,发现存不了了,因为要存一次取一次,故将该线程进入睡眠状态,也就数阻塞。所以在外面伺机*已久的取线程进来了,进行取得操作,并唤醒其它睡眠或者等待的线程(期间存线程可能已经被唤醒了,进行*了存的操作)。当再次准备继续走循环时,同样跟存一样,也是必须一取一存才可以,由于标识符的改变,故*取线程进入睡眠。以此类推
*/
//当只有存取线程的时候确实是交易输出,但是我加了一个存线程,进入死锁。解析如下:
假设存1存2线程分别进入run方法,但是只能有一个人才能做存操作,假设有幸是存1,那么存1存完后,存方法被放开了,存1存2都有可能再次做存操作,但是,不管谁做存都做不了,要等到取做完才能做存,即会有两个存线程进入等待状态,随后只有当取线程唤醒其中一个线程后才能进行存的操作,那么它又将唤醒一个线程,那么到底是唤醒存1还是存2呢?先不管,假设唤醒了存1,那存1又该唤醒谁呢?如果唤醒的是存2呢?那么取线程也就只能睡着,即下一个存线程无法解放,两个存线程就只能一直等待着,三个进入死锁。