3、传统线程同步与通信--生产消费例子

核心点:

1、锁对象必须是同一个。
2、wait()和notify()方法必须是调用锁对象的方法,而非this(线程)的。
3、在多生产多消费的时候注意使用notifyAll而不是notifyAll,否则会造成死锁

测试代码:

  1 import java.util.LinkedList;
  2 import java.util.Queue;
  3 import java.util.Random;
  4
  5 /**
  6  * 多个生产 - 消费 线程同步通信
  7  * 核心点:
  8  * 1、锁对象必须是同一个。
  9  * 2、wait()和notify()方法必须是调用锁对象的方法,而非this(线程)的。
 10  * 3、在多生产多消费的时候注意使用notifyAll而不是notifyAll
 11  * @author yzl
 12  *
 13  */
 14 public class ThreadPart_3 {
 15     public static void main(String[] args) {
 16         test();
 17     }
 18     public static void test(){
 19         final Factory factory = new Factory();
 20         Thread shengchan1 = new Thread(new Runnable() {
 21             @Override
 22             public void run() {
 23                 while(true){
 24                     factory.add();
 25                 }
 26             }
 27         });
 28         shengchan1.start();
 29         Thread shengchan2 = new Thread(new Runnable() {
 30             @Override
 31             public void run() {
 32                 while(true){
 33                     factory.add();
 34                 }
 35             }
 36         });
 37         shengchan2.start();
 38
 39         Thread xiaofei1 = new Thread(new Runnable() {
 40             @Override
 41             public void run() {
 42                 while(true){
 43                     factory.sub();
 44
 45                 }
 46             }
 47         });
 48         xiaofei1.start();
 49         Thread xiaofei2 = new Thread(new Runnable() {
 50             @Override
 51             public void run() {
 52                 while(true){
 53                     factory.sub();
 54                 }
 55             }
 56         });
 57         xiaofei2.start();
 58     }
 59 }
 60
 61 class Factory{
 62     private Queue<Integer> queue = new LinkedList<Integer>();
 63     //生产
 64     public synchronized void add(){
 65         //用while代替if来防止假唤醒
 66         while(queue.size() > 0){
 67             try {
 68                 this.wait();
 69             } catch (InterruptedException e) {
 70                 e.printStackTrace();
 71             }
 72         }
 73         Integer val = new Random().nextInt(100);
 74         queue.add(val);
 75         System.out.println("生产者:" + Thread.currentThread().getName()+" add :" + val);
 76         this.notifyAll();
 77         try {
 78             Thread.sleep(1000);
 79         } catch (InterruptedException e) {
 80             e.printStackTrace();
 81         }
 82     }
 83     //消费
 84     public synchronized void sub(){
 85         //用while代替if来防止假唤醒
 86         while(queue.size() == 0 ){
 87             try {
 88                 this.wait();
 89             } catch (InterruptedException e) {
 90                 e.printStackTrace();
 91             }
 92         }
 93         Integer val = queue.poll();
 94         System.out.println("消费者:" + Thread.currentThread().getName()+" get : " + val);
 95         this.notifyAll();
 96         try {
 97             Thread.sleep(1000);
 98         } catch (InterruptedException e) {
 99             e.printStackTrace();
100         }
101     }
102 }

运行结果示例:

 1 生产者:Thread-0 add :12
 2 消费者:Thread-3 get : 12
 3 生产者:Thread-1 add :84
 4 消费者:Thread-2 get : 84
 5 生产者:Thread-0 add :28
 6 消费者:Thread-3 get : 28
 7 生产者:Thread-1 add :60
 8 消费者:Thread-2 get : 60
 9 生产者:Thread-0 add :71
10 消费者:Thread-3 get : 71
11 生产者:Thread-1 add :63
12 消费者:Thread-3 get : 63
13 生产者:Thread-0 add :3
14 消费者:Thread-2 get : 3
15 生产者:Thread-1 add :62
16 消费者:Thread-3 get : 62
17 生产者:Thread-0 add :90
18 消费者:Thread-2 get : 90
19 生产者:Thread-1 add :9
20 消费者:Thread-3 get : 9
时间: 2024-12-17 10:38:53

3、传统线程同步与通信--生产消费例子的相关文章

Java多线程基础(四)Java传统线程同步通信技术

Java多线程基础(四)Java传统线程同步通信技术 编写代码实现以下功能 子线程循环10次,接着主线程循环100次,接着又回到子线程循环10次,接着再回到主线程又循环100次,如此循环50次. 分析 1)子线程循环10次与主线程循环100次必须是互斥的执行,不能出现交叉,下面代码中通过synchronized关键字实现此要求: 2)子线程与主线程必须交替出现,可以通过线程同步通信技术实现,下面代码中通过bShouldSub变量实现此要求: 其他需要注意的地方 1)其中business变量必须声

4.传统线程同步通信技术

1 /** 2 * 传统线程同步通信技术 3 * 4 * ******************************************* 5 * 经验: 6 * 要用到共同数据(包括共同锁)或共同算法的若干个方法应该 7 * 归在用一个类身上,这种设计正好体现了高内聚和程序的健壮性. 8 * 9 * ******************************************* 10 * 11 * @author LiTaiQing 12 */ 13 public class T

JAVA 并发编程-传统线程同步通信技术(四)

首先介绍几个概念: wait()方法 wait()方法使得当前线程必须要等待,等到另外一个线程调用notify()或者notifyAll()方法. 当前的线程必须拥有当前对象的monitor,也即lock,就是锁. 线程调用wait()方法,释放它对锁的拥有权,然后等待另外的线程来通知它(通知的方式是notify()或者notifyAll()方法),这样它才能重新获得锁的拥有权和恢复执行. 要确保调用wait()方法的时候拥有锁,即,wait()方法的调用必须放在synchronized方法或s

【java并发】传统线程同步通信技术

先看一个问题: 有两个线程,子线程先执行10次,然后主线程执行5次,然后再切换到子线程执行10,再主线程执行5次--如此往返执行50次. 看完这个问题,很明显要用到线程间的通信了, 先分析一下思路:首先肯定要有两个线程,然后每个线程中肯定有个50次的循环,因为每个线程都要往返执行任务50次,主线程的任务是执行5次,子线程的任务是执行10次.线程间通信技术主要用到wait()方法和notify()方法.wait()方法会导致当前线程等待,并释放所持有的锁,notify()方法表示唤醒在此对象监视器

传统线程同步通信技术

先看一个问题: 有两个线程,子线程先执行10次,然后主线程执行5次,然后再切换到子线程执行10,再主线程执行5次--如此往返执行50次. 看完这个问题,很明显要用到线程间的通信了, 先分析一下思路:首先肯定要有两个线程,然后每个线程中肯定有个50次的循环,因为每个线程都要往返执行任务50次,主线程的任务是执行5次,子线程的任务是执行10次.线程间通信技术主要用到 wait() 方法和 notify() 方法.wait() 方法会导致当前线程等待,并释放所持有的锁,notify() 方法表示唤醒在

【Java多线程与并发库】4.传统线程同步通信技术

我们先通过一道面试题来了解传统的线程同步通信. 题目:子线程循环10次,接着主线程循环100次,接着又回到子线程循环10次,接着再回到主线程又循环100次,如此循环50次,请写出程序. 我没有看答案,先用自己的思路写了一段代码,有一些是借鉴传统的“生产者与消费者”的多线程模型写出来的:[java] view plain copy 在CODE上查看代码片派生到我的代码片package cn.edu.hpu.test; /** * 要求的操作: * 子线程循环10次,接着主线程循环100次,接着又回

Java多线程与并发库高级应用-传统线程同步通信技术

面试题: 子线程循环10次,接着主线程循环100次,接着又回到子线程循环10次,接着又 主线程循环100次,如此循环50次,请写出程序 /** * 子线程循环10次,接着主线程循环100次,接着又回到子线程循环10次,接着又 主线程循环100次,如此循环50次,请写出程序 * * @author Administrator * */ public class TraditionalThreadCommunication { public static void main(String[] arg

(黑马Java多线程与并发库高级应用)04 传统线程同步通信技术

子线程10次,然后主线程100次,然后子线程10次,然后主线程100次.循环50次 package cn.itcast.heima2; public class TraditionalThreadComunication { public static void main(String[] args) { // TODO Auto-generated method stub Business business = new TraditionalThreadComunication().new B

C/C++ 线程同步安全队列简单实现例子

#ifndef MUTEXLOCKER_H_INCLUDED #define MUTEXLOCKER_H_INCLUDED #include <pthread.h> #include <stdexcept> class MutexLocker{ public: explicit MutexLocker(pthread_mutex_t *mutex):m_mutex(mutex){ int ret = pthread_mutex_lock(m_mutex); if(ret != 0)