Java多线程之线程通信生产者消费者模式及等待唤醒机制代码详解

  

<强>前言
  

  

前面的例子都是多个线程在做相同的操作,比如4个线程都对共享数据做票——操作。大多情况下,程序中需要不同的线程做不同的事,比如一个线程对共享变量做票+ +操作,另一个线程对共享变量做票——操作,这就是大名鼎鼎的生产者和消费者模式。
  

  

<强>正文
  

  

<强>一、生产者——消费者模式也是多线程
  

  

生产者和消费者模式也是多线程的范例。所以其编程需要遵循多线程的规矩。
  

  

首先,既然是多线程,就必然要使用同步。上回说到,同步关键字在修饰函数的时候,使用的是“这”锁,所以在同一个类中的函数被同步修饰后,使用的是同一把锁。线程调用这些函数时,不管调用的是机票+ +操作函数,还是票——函数,都会先去判断是否加锁了,得到锁之后再去进行具体的操作。
  

  

我们先用代码把程序中的资源,生产者,消费者表示出来。

        包com.jimmy.ThreadCommunication;   类资源{//资源类   私人字符串productName;//资源名称   私人int数=1;//资源编的号   公共空间产生(字符串名称){//生产资源函数   这一点。productName=名称+计数;   数+ +;//资源编号递增,用来模拟资源递增   System.out.println (Thread.currentThread () . getname() +“…生产者…”+ this.productName);   }   公共空间使用(){//消费资源函数   System.out.println (Thread.currentThread () . getname() +“…消费者…”+ this.productName);   }   }   类生产商实现Runnable{//生产者类,用于开启生产者线程   私人资源res;//生产者初始化就要分配资源   公共生产资源(res) {   这一点。res=res;   }   @Override   公共空间run () {   for (int i=0;我& lt;10;我+ +){   res.produce(“面包”);//循环生产10次   }   }   }   类最大限度实现Runnable{//消费者类,用于开启消费者线程   私人资源res;//同理,消费者一初始化也要分配资源   公众最大限度(资源res) {   这一点。res=res;   }   @Override   公共空间run () {   for (int i=0;我& lt;10;我+ +){   res.consume ();//循环消费10次   }   }   }   公开课ProducerAndConsumer1 {   公共静态void main (String [] args) {   资源资源=新的资源();//实例化资源   制片人生产者=new(资源);//实例化生产者和消费者类,它们取得同一个资源   消费者最大限度=new最大限度(资源);   线程threadProducer=新线程(生产者);//创建1个生产者线程   线程threadComsumer=新线程(消费者);//创建1个消费者线程   threadProducer.start ();//分别开启线程   threadComsumer.start ();   }   }      

架子搭好了,就来运行一下,当然会出现错误的结果,如下所示:

        Thread-0…生产者. . bread1   Thread-0…生产者. . bread2   Thread-0…生产者. . bread3   Thread-0…生产者. . bread4   Thread-0…生产者. . bread5   线程1…消费者. . bread1   线程1…消费者. . bread6   线程1…消费者. . bread6   线程1…消费者. . bread6   线程1…消费者. . bread6   线程1…消费者. . bread6   Thread-0…生产者. . bread6   Thread-0…生产者. . bread7   线程1…消费者. . bread6   线程1…消费者. . bread8   线程1…消费者. . bread8   线程1…消费者. . bread8   Thread-0…生产者. . bread8   Thread-0…生产者. . bread9   Thread-0…生产者. . bread10      

很明显,出现了线程安全错误。这时,就需要“同步”来保证对共享变量的互斥访问。上面代码中需要同步的就是资源资源类中的生产和消费方法,分别使用同步来修饰,由于同步修饰方法时使用的是“这”锁,所以同一个类中的所有被修饰的方法用的都是同一个锁,那么线程一次只能访问其中一个方法。加锁后的资源类方法如下:

        类资源{//资源类   私人字符串productName;//资源名称   私人int数=1;//资源编的号   公共空隙产生同步(字符串名称){//生产资源函数   这一点。productName=名称+计数;   数+ +;//资源编号递增,用来模拟资源递增   System.out.println (Thread.currentThread () . getname() +“…生产者…”+ this.productName);   }   公共同步无效消耗(){//消费资源函数   System.out.println (Thread.currentThread () . getname() +“…消费者…”+ this.productName);   }   }

Java多线程之线程通信生产者消费者模式及等待唤醒机制代码详解