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版本 改 ...
随机推荐
- Python分布式爬虫必学框架Scrapy打造搜索引擎 学习教程
Python分布式爬虫打造搜索引擎Scrapy精讲—用Django实现搜索的自动补全功能 elasticsearch(搜索引擎)提供了自动补全接口 1.创建搜索自动补全字段suggest自动补全需要用 ...
- leetcode.字符串.344反转字符串-Java
1. 具体题目 编写一个函数,其作用是将输入的字符串反转过来.输入字符串以字符数组 char[] 的形式给出.不要给另外的数组分配额外的空间,你必须原地修改输入数组.使用 O(1) 的额外空间解决这一 ...
- kmp(多次可重叠匹配)
http://acm.hdu.edu.cn/showproblem.php?pid=1686 Oulipo Problem Description The French author Georges ...
- B bearBaby loves sleeping
链接:https://ac.nowcoder.com/acm/contest/338/B来源:牛客网 题目描述 Sleeping is a favorite of little bearBaby, b ...
- SQL 查询 group by 的使用注意点
今天用SQL Server尝试实现一个SQL语句的时候,报了如标题所示的错误,通过在百度里面搜索,并亲自动手实现,终于发现问题所在,现在把它记录下来. 语句如下: select [OrderI ...
- Java 8实战之读书笔记一:内容简介
本书的主要内容如下: 如何使用Java 8新增的强大特性 如何编写能有效利用多核架构的程序 重构.测试和调试 怎样高效地应用函数式编程 目录: 第一部分 基础知识 第1 章 为什么要关心Jav ...
- php中xml元素取值问题
<?php $_xml = <<<_xml <?xml version="1.0" encoding="utf-8"?> & ...
- 抽象类(abstract)与接口(interface)的区别
如果一个类中包含抽象方法,那么这个类就是抽象类.abstract只能用来修饰类或者方法,不能用来修饰属性. 接口是指一个方法的集合,接口中的所有方法都没有方法体.接口通过关键字interface实现. ...
- 没有dockerfile的情况下如何查看docker的镜像信息
前言 参考资料 https://baijiahao.baidu.com/s?id=1564406878758073&wfr=spider&for=pc 很实用的功能哈.. 步骤 1.先 ...
- bzoj3812 主旋律 容斥+状压 DP
题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=3812 题解 考虑对于图的联通性的 DP 的一般套路:总方案 - 不连通的方案. 那么我们只需要 ...