Java学习之线程通信(多线程(synchronized))--生产者消费者
分析线程经典案例生产者消费者
/**
共享数据
*/
class Resource
{
private String name;
private int count=1;
private boolean flag=false; public synchronized void set(String name)
{
if(flag)
try{this.wait();}catch(InterruptedException e){}
this.name=name+count;
count++;
System.out.println(Thread.currentThread().getName() + "...生产者..." + this.name);
flag = true;
notify();
} public synchronized void out()
{
if(!flag)
try{this.wait();}catch(InterruptedException e){}
System.out.println(Thread.currentThread().getName() + "==消费者==" + this.name);
flag = false;
notify();
}
} //定义线程任务(生产者线程)
class Producer implements Runnable
{
private Resource r; Producer(Resource r)
{
this.r=r;
}
public void run()
{
while(true)
{
r.set("商品");
}
}
}
//定义线程任务(消费者线程)
class Consumer implements Runnable
{
private Resource r; Consumer(Resource r)
{
this.r=r;
} public void run()
{
while(true)
{
r.out();
}
}
} class ProducerConsumerDemo
{
public static void main(String[] args)
{
//实例化共享资源
Resource r = new Resource();
//实例化线程任务,指定共享资源
Producer p=new Producer(r);
Consumer c=new Consumer(r);
//实例化线程,指定线程任务
Thread t0=new Thread(p);
Thread t1=new Thread(p);
Thread t2=new Thread(c);
Thread t3=new Thread(c);
//开启线程,执行线程任务中的run方法
t0.start();
t1.start();
t2.start();
t3.start();
}
}
运行结果:
结果分析:
那么怎么再判断flag呢?while
代码如下:
class Resource
{
private String name;
private int count=1;
private boolean flag=false; public synchronized void set(String name) // 有两个线程t0 t1
{
while(flag)
try{this.wait();}catch(InterruptedException e){}
this.name=name+count;
count++;
System.out.println(Thread.currentThread().getName() + "...生产者..." + this.name);
flag = true;
notify();
} public synchronized void out() // 有两个线程t2 t3
{
while(!flag)
try{this.wait();}catch(InterruptedException e){}
System.out.println(Thread.currentThread().getName() + "==消费者==" + this.name);
flag = false;
notify();
}
}
结果出现死锁:
结果分析:
通过分析,那能不能每次唤醒只唤醒对方线程(如生产者线程只唤醒消费者线程,消费者线程只唤醒生产者线程),查看Object对象方法中没有,但是有一个notifyAll()方法,实在不行就把所有阻塞线程(相同同步锁的线程)都唤醒。
class Resource
{
private String name;
private int count=1;
private boolean flag=false; public synchronized void set(String name) // 有两个线程t0 t1
{
while(flag)
try{this.wait();}catch(InterruptedException e){}
this.name=name+count;
count++;
System.out.println(Thread.currentThread().getName() + "...生产者..." + this.name);
flag = true;
notifyAll();
} public synchronized void out() // 有两个线程t2 t3
{
while(!flag)
try{this.wait();}catch(InterruptedException e){}
System.out.println(Thread.currentThread().getName() + "==消费者==" + this.name);
flag = false;
notifyAll();
}
}
结果:
这样就可以了。
总结:
if判断只能判断一次,如果执行等待方法,下次唤醒的线程获取执行权后(唤醒后的线程会从上次等待位置,向下执行)就不能再判断
while判断解决唤醒的线程获取执行权后无法判断
notify:只能唤醒任意一个线程,有可能会唤醒本方线程,while+notify会导致死锁
notifyAll:解决了死锁问题
Java学习之线程通信(多线程(synchronized))--生产者消费者的更多相关文章
- Java学习之线程通信(多线程(Lock))--生产者消费者
SDK1.5版本以后对synchronized的升级,其思想是:将同步和锁封装成对象,其对象中包含操作锁的动作. 代码: //1.导入包 import java.util.concurrent.loc ...
- 【多线程】java多线程实现生产者消费者模式
思考问题: 1.为什么用wait()+notify()实现生产者消费者模式? wait()方法可以暂停线程,并释放对象锁 notify()方法可以唤醒需要该对象锁的其他线程,并在执行完后续步骤,到了s ...
- Java并发包——线程通信
Java并发包——线程通信 摘要:本文主要学习了Java并发包里有关线程通信的一些知识. 部分内容来自以下博客: https://www.cnblogs.com/skywang12345/p/3496 ...
- java多线程模拟生产者消费者问题,公司面试常常问的题。。。
package com.cn.test3; //java多线程模拟生产者消费者问题 //ProducerConsumer是主类,Producer生产者,Consumer消费者,Product产品 // ...
- Java多线程_生产者消费者模式2
在我的上一条博客中,已经介绍到了多线程的经典案列——生产者消费者模式,但是在上篇中用的是传统的麻烦的非阻塞队列实现的.在这篇博客中我将介绍另一种方式就是:用阻塞队列完成生产者消费者模式,可以使用多种阻 ...
- java多线程解决生产者消费者问题
import java.util.ArrayList; import java.util.List; /** * Created by ccc on 16-4-27. */ public class ...
- Java并发基础--线程通信
java中实现线程通信的四种方式 1.synchronized同步 多个线程之间可以借助synchronized关键字来进行间接通信,本质上是通过共享对象进行通信.如下: public class S ...
- Android-Java多线程通讯(生产者 消费者)&10条线程对-等待唤醒/机制的管理
上一篇博客 Android-Java多线程通讯(生产者 消费者)&等待唤醒机制 是两条线程(Thread-0 / Thread-1) 在被CPU随机切换执行: 而今天这篇博客是,在上一篇博客A ...
- 【多线程】--生产者消费者模式--Lock版本
在JDK1.5发布后,提供了Synchronized的更优解决方案:Lock 和 Condition 我们使用这些新知识,来改进例子:[多线程]--生产者消费者模式--Synchronized版本 改 ...
随机推荐
- get_date.sh
#!/usr/bin#####################################################################日期函数处理#获取某个月份的天数 getM ...
- ssh公私钥免密登陆
简介ssh Secure Shell(简写SSH) 为一项建立在应用层和传输层基础上的安全协议,专门为远程登录会话和其他网络服务提供安全性的协议. SSH安全机制分为两种,一种是基于口令的安全认证,一 ...
- an安装jenkins时遇到ERROR: No Java executable found in current PATH: /bin:/usr/bin:/sbin:/usr/sbin的问题
# sudo /etc/init.d/jenkins restartERROR: No Java executable found in current PATH: /bin:/usr/bin:/sb ...
- [Linux] 020 RPM 包的命名原则与其依赖性
1. RPM 包命名原则 例如:httpd-2.2.15-15.e16.centos.1.i686.rpm 字符 释义 httpd 软件包名 2.2.15 软件版本 15 软件发布的次数 e16.ce ...
- 移动端web整理 移动端问题总结,移动web遇到的那些坑
meta基础知识 H5页面窗口自动调整到设备宽度,并禁止用户缩放页面 忽略将页面中的数字识别为电话号码 忽略Android平台中对邮箱地址的识别 当网站添加到主屏幕快速启动方式,可隐藏地址栏,仅针对i ...
- P4929 【模板】舞蹈链(DLX)
题目背景 本题是舞蹈链模板——精确覆盖问题 题目描述 给定一个N行M列的矩阵,矩阵中每个元素要么是1,要么是0 你需要在矩阵中挑选出若干行,使得对于矩阵的每一列j,在你挑选的这些行中,有且仅有一行的第 ...
- opencv2——直方图5
(一)图像直方图 图像的构成是有像素点构成的,每个像素点的值代表着该点的颜色(灰度图或者彩色图).所谓直方图就是对图像的中的这些像素点的值进行统计,得到一个统一的整体的灰度概念.直方图的好处就在于可以 ...
- Codeforces - 1191E - Tokitsukaze and Duel - 博弈论 - 尺取
https://codeforc.es/contest/1191/problem/E 参考自:http://www.mamicode.com/info-detail-2726030.html 和官方题 ...
- Java 小技巧和在Java避免NullPonintException的最佳方法(翻译)
前几天就g+里面看到有人引用这篇博文.看了一下.受益颇多. 所以翻译过来,希望和大家一起学习.本人英语水平有限,假设有错,请大家指正. 原文地址(须要翻墙):http://ja ...
- HR面试总结
求职面试HR最欣赏的自我介绍 2015-02-25 来源:www.cnrencai.com 浏览:391 明明很有能力的你,在面试中却不能发挥出色?来看看是不是自我介绍环节出了问题. 回答面试题目 ...