多线程通信(生产者与消费者)

来源:互联网 发布:ubuntu nginx 配置 编辑:程序博客网 时间:2024/05/03 16:19
java中多线程之间的通信,本篇主要说明的是多线程之间的通信,共同操作一个资源,以及线程中出现的死锁现象,以及出现线程中重复生产的问题,通过同步线程可以解决这些问题,同步线程同一进程的多个线程共享同一片存储空间,在带来方便的同时,也带来了访问冲突这个严重的问题。Java语言提供了专门机制以解决这种冲突,有效避免了同一个数据对象被多个线程同时访问。 由于我们可以通过 private 关键字来保证数据对象只能被方法访问,所以我们只需针对方法提出一套机制,这套机制就是synchronized 关键字,它包括两种用法:synchronized 方法和 synchronized 块。
这下面的代码中都可以详细的体现出来,其代码如下:
public class ProducerCustumerDemo {

 /**
  * @param args
  */
 public static void main(String[] args) {
  //着这里传建一个资源类,是为了多线程之间保持操作的是一个资源,用构造函数等的方式传递到线程类中
  Resouce resouce=new Resouce();
  //创建多个生产和消费的线程类
  Producer producer1=new Producer(resouce);
  Producer producer2=new Producer(resouce);
  Custumer custumer1=new Custumer(resouce);
  Custumer custumer2=new Custumer(resouce);
  
  new Thread(producer1).start();
  new Thread(producer2).start();
  new Thread(custumer1).start();
  new Thread(custumer2).start();
 }

 //定义一个线程共享的一个资源类
 static class Resouce{
  //商品的ID
  private int id;
  //商品的名字
  private String name;
  //用于判断是否生产或者消费的数据,
  private boolean flag=false;
  
  //同步方法,是为了线程之间保持数据的一致性,不会出现意外的情况发生
  public synchronized void set(String name)
  {
   //这里用while循环是为了防止多个线程,重复生产的情况
   while(flag)
    try {
     this.wait();//线程等待,也即是放弃运行的资格
    } catch (Exception e) {
     // TODO: handle exception
    }
   this.name=name+id++;
   //获取当前线程的名称
   String currentThread=Thread.currentThread().getName();
   System.out.println(currentThread+"生产"+this.name+"....");
   //消费之后,让消费的线程继续消费该商品
   this.flag=true;
   this.notifyAll();
  }
  
  public synchronized void out()
  {
   //这里用while循环是为了防止多个线程,多消费情况
   while(!flag)
    try {
     this.wait();//线程等待,也即是放弃运行的资格
    } catch (Exception e) {
     // TODO: handle exception
    }
   //获取当前线程的名称
   String currentThread=Thread.currentThread().getName();
   System.out.println(".........."+currentThread+"消费了"+this.name);
   //消费之后,让生产的线程继续生产产品
   this.flag=false;
   //唤醒线程池中的线程,这里不用notiy()是因为这里可能出现死锁的现象
   this.notifyAll();
  }
 }
 
 //生产商品的线程类
 static class Producer implements Runnable{
  //顶一个资源类对象
  Resouce resouce=null;
  public Producer(Resouce re) {
   this.resouce=re;
  }
  @Override
  public void run() {
   for(int i=0;i<100;i++)
   resouce.set("小米电视");
  }
 }
 
 //消费商品的线程类
 static class Custumer implements Runnable{
  Resouce resouce=null;
  public Custumer(Resouce re) {
   this.resouce=re;
  }
  public void run() {
   for(int i=0;i<100;i++)
   resouce.out();
  }
  
 }
}


0 0
原创粉丝点击