<强>前言强>
前面的例子都是多个线程在做相同的操作,比如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多线程之线程通信生产者消费者模式及等待唤醒机制代码详解