多线程-生产者与消费者(存储数据与打印数据)

无线程同步:

存储数据:

 1 public class Storage {
 2     int data;
 3
 4     public int getData() {
 5         return data;
 6     }
 7
 8     public  void setData(int data) {
 9         this.data = data;
10     }
11
12 }

产生数据:

 1 public class Counter implements Runnable {
 2     private Storage storage;
 3
 4     public Counter(Storage storage) {
 5         this.storage = storage;
 6     }
 7
 8     int count = 0;
 9
10     @Override
11     public void run() {
12         while (true) {
13
14             storage.setData(count);
15             System.out.println("Storage data set:" + count);
16
17             try {
18                 Thread.sleep((int) (Math.random() * 1000));
19             } catch (InterruptedException e) {
20
21                 e.printStackTrace();
22             }
23             count++;
24         }
25
26     }
27
28 }

读取数据:

 1 public class Printer extends Thread {
 2     private Storage storage;
 3
 4     public Printer(Storage storage) {
 5         this.storage = storage;
 6     }
 7
 8     public void run() {
 9         while (true) {
10
11             System.out.println("Storage data print:" + storage.getData());
12
13             try {
14                 Thread.sleep((int) (Math.random() * 1000));
15             } catch (InterruptedException e) {
16
17                 e.printStackTrace();
18             }
19
20         }
21
22     }
23
24 }

测试类:

 1 public class TestPrint {
 2
 3     public static void main(String[] args) {
 4         Storage storage = new Storage();
 5
 6         Counter counter = new Counter(storage);
 7         Thread th1 = new Thread(counter);
 8
 9         Printer th2 = new Printer(storage);
10         th1.start();
11         th2.start();
12     }
13
14 }

运行结果:

分析运行结果可发现两个问题

1、生产者产生的资源可能没有被消费者获取

2、生产者产生的资源可能被消费者重复取得

造成这些问题的原因是两个线程在访问同一个对象时没有考虑同步的控制。

当消费者尚未取得资源时,生产者可能已经产生新的资源,使消费者错过一些资源

当生产者尚未产生新资源时,消费者再次执行get()方法,造成资源被重复获取

解决前述问题的关键是引入线程之间的同步控制逻辑 ,通过synchronized关键字锁定共享对象

方法名前加synchronized关键字标记

用synchronized(Object) {…}标记锁定的代码

当线程执行由synchronized关键字控制的代码时,就锁定了共享对象。其他线程如果需要操作该对象,就必须等待该线程执行完受保护的代码

修改后:

 1 public class Storage {
 2     int data;
 3     private boolean getable;
 4
 5     public synchronized int getData() {
 6         while (getable == false) {
 7             try {
 8                 wait();
 9             } catch (InterruptedException e) {
10                 e.printStackTrace();
11             }
12         }
13         getable = false;
14         notifyAll();
15         return data;
16     }
17
18     public synchronized void setData(int data) {
19
20         while (getable == true) {
21             try {
22                 wait();
23             } catch (InterruptedException e) {
24             }
25         }
26         this.data = data;
27         getable = true;
28         notifyAll();
29     }
30
31 }

运行结果:

多线程-生产者与消费者(存储数据与打印数据)

时间: 2024-10-14 01:08:38

多线程-生产者与消费者(存储数据与打印数据)的相关文章

JAVA基础再回首(二十五)——Lock锁的使用、死锁问题、多线程生产者和消费者、线程池、匿名内部类使用多线程、定时器、面试题

JAVA基础再回首(二十五)--Lock锁的使用.死锁问题.多线程生产者和消费者.线程池.匿名内部类使用多线程.定时器.面试题 版权声明:转载必须注明本文转自程序员杜鹏程的博客:http://blog.csdn.net/m366917 我们来继续学习多线程 Lock锁的使用 虽然我们可以理解同步代码块和同步方法的锁对象问题,但是我们并没有直接看到在哪里加上了锁,在哪里释放了锁,为了更清晰的表达如何加锁和释放锁,JDK5以后提供了一个新的锁对象Lock Lock void lock():获取锁 v

多线程——生产者和消费者的问题

生产者和消费者问题的产生 生产者和消费者是指俩个不同的线程对象,操作统一资源的情况:生产者负责生产数据,消费者负责消费数据,生产者每生产完一组数据后,消费者  消费一组数据, Object对多线程的支持:  wait();等待被唤醒  notify();唤醒  notifyAll();唤醒所有 sleep()和wait()的区别: sleep()属于Thread类,类似于一个闹钟,只持续一定时间.wait()属于Object类,需要被notify()唤醒,如果不唤醒就会一直等待下去 具体案例如下

Java多线程--生产者与消费者问题

说明 Java中,线程之间的通信主要是由java.lang.Object类提供的wait.notify和notifyAll这3个方法来完成: ①对象的wait方法被调用后,线程进入对象的等待队列中,并释放对象锁,其它线程可以竞争使用此对象锁:sleep方法使得一个线程进入睡眠状态,但是线程所占有的资源并没有释放. ②当对象的notify方法被调用,该方法会从对象的等待队列中随机取出一个线程来唤醒:notifyAll是唤醒等待队列中所有线程,这些线程会与其它正在执行的线程共同竞争对象锁. ③wai

多线程——生产者和消费者(四)

通过前面三篇博客的介绍,基本上对Java的多线程有了一定的了解了,然后这篇博客根据生产者和消费者的模型来介绍Java多线程的一些其他知识. 我们这里的生产者和消费者模型为: 生产者Producer 生产某个对象(共享资源),放在缓冲池中,然后消费者从缓冲池中取出这个对象.也就是生产者生产一个,消费者取出一个.这样进行循环.   第一步:我们先创建共享资源的类 Person,它有两个方法,一个生产对象,一个消费对象 ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16

多线程生产者、消费者模式中,如何停止消费者?多生产者情况下对“毒丸”策略的应用。

生产者.消费者模式是多线程中的经典问题.通过中间的缓冲队列,使得生产者和消费者的速度可以相互调节. 对于比较常见的单生产者.多消费者的情况,主要有以下两种策略: 通过volatile boolean producerDone =false 来标示是否完成.生产者结束后标示为true, 消费者轮询这个变量来决定自己是否退出. 这种方式对producerDone产生比较大的争用,实现起来也有诸多问题需要考虑. 比较经典的"毒丸"策略,生产者结束后,把一个特别的对象:"毒丸&quo

2015阿里巴巴校招附加题:多线程-生产者和消费者

今天参加了阿里2015校招实习生的笔试. 选择题部分确实有水平,由于基础一般再加上没做准备,打得一塌糊涂,目测已经阵亡了,不过附加题的最后一个还是很基础的,关于java的多线程中的生产者和消费者的问题,在此感谢@绝影. 题目: 有个篮子,一个人不停地往里面放苹果,另一个不停地从里面拿出来苹果,篮子最多能放5个苹果,苹果数量无限.用Java模拟实现. 实现过程: 主类: class ProducerConsumer { public static void main(String[] args)

多线程——生产者与消费者(多)问题解决

package 多线程; public class PandC { public static void main(String[] args) { // Producer p= new Producer(); // Consumer c = new Consumer(); // new Thread(p,"生产者").start(); // new Thread(p,"生产者").start(); // new Thread(c,"消费者").

7.2.6 - 并发多线程 生产者,消费者

一 生产者消费者模型介绍 为什么要使用生产者消费者模型 生产者指的是生产数据的任务,消费者指的是处理数据的任务,在并发编程中,如果生产者处理速度很快,而消费者处理速度很慢,那么生产者就必须等待消费者处理完,才能继续生产数据.同样的道理,如果消费者的处理能力大于生产者,那么消费者就必须等待生产者.为了解决这个问题于是引入了生产者和消费者模式. 什么是生产者和消费者模式 生产者消费者模式是通过一个容器来解决生产者和消费者的强耦合问题.生产者和消费者彼此之间不直接通讯,而通过阻塞队列来进行通讯,所以生

angular2动态增加一行组件和删除组件示例改进版(增加了添加数据、清空数据、打印数据功能)

初始效果 点击添加行  点击添加数据  点击打印数据  点击清空数据 TS 部分代码讲解 /** * 获取数组对象 */ get arrayList() { return this.fg.get('arrayList') as FormArray; } 获取的 HTML页面的控件arrayList 对象 /** * 添加数据 */ addData(){ this.arrayList.controls.forEach((item,index)=>{ //此处的this.arrayList出自 ge