java多线程---等待/唤醒以及生产者消费者经典同步synchronized的实现

来源:互联网 发布:linux redhat中文乱码 编辑:程序博客网 时间:2024/06/06 03:42

一个线程开始执行后就进入等待,然后另外一个线程来唤醒它

代码如下:

package com.zcj.thread02;public class Thread01 {   private static Object object= new Object();   public static void main(String[] args) {  ThreadA theA = new ThreadA(object);  ThreadB threadB = new ThreadB(object);  theA.start();  try {Thread.sleep(3000);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}  threadB.start();   }}class ThreadA extends Thread{private Object object;public ThreadA(Object object){this.object=object;}@Overridepublic void run(){synchronized (object) {try {System.out.println("我开始等待。。。");object.wait();System.out.println("我被唤醒了,不再等待");} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}}class ThreadB extends Thread{private Object object;public ThreadB(Object object){this.object=object;}@Overridepublic void run(){synchronized (object) {object.notify();}}}
一个消费者和一个生产者的同步问题:

package com.zcj.thread02;public class Thread01 {   public int count= 0;   public  void produce(){   synchronized (this) {if(count==1){try {this.wait();} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}     }System.out.println("我生产商品!");count=1;this.notify();}   }   public void consumer(){   synchronized (this) {    if(count==0){    try {    this.wait();} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}    }    System.out.println("我消费商品");    count=0;    this.notify();}   }   public static void main(String[] args) {  Thread01 thd = new Thread01();  ThreadA threadA = new ThreadA(thd);  ThreadB threadB = new ThreadB(thd);  threadA.start();  threadB.start();   }}class ThreadA extends Thread{private Thread01 thd;public ThreadA(Thread01 thd){this.thd=thd;}@Overridepublic void run(){    while(true){    thd.produce();    }}}class ThreadB extends Thread{private Thread01 thd;public ThreadB(Thread01 thd){this.thd=thd;}@Overridepublic void run(){while(true){thd.consumer();}}}

多个生产者和多个消费者的例子如下:注意其中变化的部分,while和notifyAll();不过使用synchronized有个问题就是唤醒的时候不能有所指定的唤醒对应的线程:

首先解释下这里为什么会使用while语句来判断:因为如果在用if的时候,当线程获得锁再次进入临界区就不会再去判断条件了,多个线程一起工作的时候就可能导致count的值超过1,另外在多个消费线程在消费的时候也可能导致下面count最终消费后的数量低于0,这样不就不符合逻辑了。使用notifyAll的原因是比如多个生产者和多个消费者一起工作,假如某个生产者开始等待,他唤醒的可能是另外一个生产者,这样另外一个生产者也进入等待,就存在一种情况导致消费者一直得不到唤醒,任务就进行不了了

package com.zcj.thread02;public class Thread01 {   public int count= 0;   public  void produce(){   synchronized (this) {while(count==1){try {this.wait();} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}     }System.out.println("我生产商品!");count=1;this.notifyAll();}   }   public void consumer(){   synchronized (this) {    while(count==0){    try {    this.wait();} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}    }    System.out.println("我消费商品");    count=0;    this.notifyAll();}   }   public static void main(String[] args) {  Thread01 thd = new Thread01();  ThreadA threadA = new ThreadA(thd);  ThreadA threadA1 = new ThreadA(thd);  ThreadB threadB = new ThreadB(thd);  ThreadB threadB1 = new ThreadB(thd);  threadA.start();  threadA1.start();  threadB.start();  threadB1.start();   }}class ThreadA extends Thread{private Thread01 thd;public ThreadA(Thread01 thd){this.thd=thd;}@Overridepublic void run(){    while(true){    thd.produce();    }}}class ThreadB extends Thread{private Thread01 thd;public ThreadB(Thread01 thd){this.thd=thd;}@Overridepublic void run(){while(true){thd.consumer();}}}




0 0
原创粉丝点击