生产者和消费者问题(synchronized、Lock)
1.synchronized的生产者和消费者
synchronized是锁住对象
this.wait()释放了锁 并等待 this.notify()随机通知并唤醒同一个对象中的一个线程
this.notifyAll()通知并唤醒同一个对象中的所有线程
注(遇到的问题):若生产消费者模型中生产者和消费者都只有一个线程的话只用this.notify()就可以了 若有多个线程必须用this.notifyAll()
因为this.notify()只通知唤醒一个线程 若只有一个生产者线程在跑 通知唤醒到了另一个生产者线程 导致所有线程等待 造成死锁 休眠判断用while不能用if
因为notify可能假唤醒通知 用while保证wait休眠条件
public class Juc3 {
public static void main(String[] args){
Data data = new Data();
new Thread(()->{
for (int i = 0; i < 10; i++) {
try {
data.increment();
}catch (Exception e){
e.printStackTrace();
}
}
},"A").start();
new Thread(()->{
for (int i = 0; i < 10; i++) {
try {
data.decrement();
}catch (Exception e){
e.printStackTrace();
}
}
},"B").start();
new Thread(()->{
for (int i = 0; i < 10; i++) {
try {
data.increment();
}catch (Exception e){
e.printStackTrace();
}
}
},"C").start();
new Thread(()->{
for (int i = 0; i < 10; i++) {
try {
data.decrement();
}catch (Exception e){
e.printStackTrace();
}
}
},"D").start();
}
}
//类中的两个方法synchronized锁 如果new一个对象 这个对象的两个方法锁是同一个锁!!!
//同一个对象中如increment方法this.notify();通知锁取消等待就是通知了decrement方法
class Data{
private int number=0;
//+1 必须有synchronized
//等待必须用while 不用if 防止虚假唤醒
//生产消费者业务代码流程其实就是1.等待2.通知
public synchronized void increment() throws InterruptedException {
while (number!=0){
this.wait();
}
number++;
System.out.println(Thread.currentThread().getName()+"=>"+number);
//通知其它线程我执行完了+1
this.notifyAll();
}
//-1
public synchronized void decrement() throws InterruptedException {
while (number==0){
this.wait();
}
number--;
System.out.println(Thread.currentThread().getName()+"=>"+number);
//通知其它线程我执行完了-1
this.notifyAll();
}
}
2.Lock的生产者和消费者
synchronized
Lock lock = new ReentrantLock();
lock加锁lock.lock();
lock解锁lock.unlock(); 解锁步骤必须放在try的finally中以防异常 Condition condition = lock.newCondition();
condition对象作线程等待condition.await() 线程唤醒condition.signalAll()
//Lock的生产者和消费者
class LockTest{
public static void main(String[] args) {
LockData data = new LockData();
new Thread(()->{
for (int i = 0; i < 10; i++) {
try {
data.increment();
}catch (Exception e){
e.printStackTrace();
}
}
},"A").start(); new Thread(()->{
for (int i = 0; i < 10; i++) {
try {
data.decrement();
}catch (Exception e){
e.printStackTrace();
}
}
},"B").start(); new Thread(()->{
for (int i = 0; i < 10; i++) {
try {
data.increment();
}catch (Exception e){
e.printStackTrace();
}
}
},"C").start(); new Thread(()->{
for (int i = 0; i < 10; i++) {
try {
data.decrement();
}catch (Exception e){
e.printStackTrace();
}
}
},"D").start();
}
} class LockData{
private int number=0;
Lock lock = new ReentrantLock();
Condition condition = lock.newCondition();
//+1
public void increment() {
lock.lock();
try {
while (number!=0){
condition.await();
}
number++;
System.out.println(Thread.currentThread().getName()+"=>"+number);
//通知其它线程我执行完了+1
condition.signalAll();
}catch (Exception e){
e.printStackTrace();
}finally {
lock.unlock();
}
}
//-1
public void decrement() {
lock.lock();
try {
while (number==0){
condition.await();
}
number--;
System.out.println(Thread.currentThread().getName()+"=>"+number);
//通知其它线程我执行完了-1
condition.signalAll();
}catch (Exception e){
e.printStackTrace();
}finally {
lock.unlock();
}
}
}
3.指定唤醒某个方法的线程
上述2个例子是以不同形式实现的同样的代码
因此发现一个问题
唤醒的是同一个对象中的随机的方法或者所有方法 没有指定特定的方法
如A()中唤醒B()唤醒C()唤醒A()循环的话
Condition condition = lock.newCondition();
Condition condition1 = lock.newCondition();
可以新增多个condition对象
condition1.await()或condition1.signal()让特定的condition对象休眠/唤醒
class LockTest1{
public static void main(String[] args) {
LockData1 data = new LockData1();
new Thread(()->{
for (int i = 0; i < 10; i++) {
try {
data.A();
}catch (Exception e){
e.printStackTrace();
}
}
}).start();
new Thread(()->{
for (int i = 0; i < 10; i++) {
try {
data.B();
}catch (Exception e){
e.printStackTrace();
}
}
}).start();
new Thread(()->{
for (int i = 0; i < 10; i++) {
try {
data.C();
}catch (Exception e){
e.printStackTrace();
}
}
}).start();
}
}
class LockData1{
private int num=1;
Lock lock = new ReentrantLock();
Condition condition1 = lock.newCondition();
Condition condition2 = lock.newCondition();
Condition condition3 = lock.newCondition();
//A 1
public void A() {
lock.lock();
try {
while (num!=1){
condition1.await();
}
System.out.println(Thread.currentThread().getName()+"=>"+num);
num=2;
condition2.signalAll();
}catch (Exception e){
e.printStackTrace();
}finally {
lock.unlock();
}
}
//B 2
public void B() {
lock.lock();
try {
while (num!=2){
condition2.await();
}
System.out.println(Thread.currentThread().getName()+"=>"+num);
num=3;
condition3.signalAll();
}catch (Exception e){
e.printStackTrace();
}finally {
lock.unlock();
}
}
//C 3
public void C() {
lock.lock();
try {
while (num!=3){
condition3.await();
}
System.out.println(Thread.currentThread().getName()+"=>"+num);
num=1;
condition1.signalAll();
}catch (Exception e){
e.printStackTrace();
}finally {
lock.unlock();
}
}
}
生产者和消费者问题(synchronized、Lock)的更多相关文章
- 第44天学习打卡(JUC 线程和进程 并发和并行 Lock锁 生产者和消费者问题 如何判断锁(8锁问题) 集合类不安全)
什么是JUC 1.java.util工具包 包 分类 业务:普通的线程代码 Thread Runnable 没有返回值.效率相比Callable相对较低 2.线程和进程 进程:一个程序.QQ.exe, ...
- Java 多线程之生产者消费者(多个生成者多个消费者)synchronized 和lock多线程通讯和同步实现
public class ProducterConsumerSample { public static void main(String[] args) { Resourse res = new R ...
- JAVA基础再回首(二十五)——Lock锁的使用、死锁问题、多线程生产者和消费者、线程池、匿名内部类使用多线程、定时器、面试题
JAVA基础再回首(二十五)--Lock锁的使用.死锁问题.多线程生产者和消费者.线程池.匿名内部类使用多线程.定时器.面试题 版权声明:转载必须注明本文转自程序猿杜鹏程的博客:http://blog ...
- 多生产者多消费者(第一种方式),基于synchronized,wait,notifyAll
生产者消费者模式描述的是协调与协作关系.比如一个人正在准备食物(生产者),而另一个人正在吃(消费者),他们使用一个共用 的桌子用于放置盘子和取走盘子,生产者准备食物,如果桌子上已经满了就等待,消费者( ...
- 同步锁Lock & 生产者和消费者案例
显示锁 Lock ①在 Java 5.0 之前,协调共享对象的访问时可以使用的机 制只有 synchronized 和 volatile . Java 5.0 后增加了一些 新的机制,但并不是一种替代 ...
- JUC 并发编程--02,生产者和消费者 synchronized的写法 , juc的写法. Condition的用法
synchronized的写法 class PCdemo{ public static void main(String[] args) { //多个线程操作同一资源 Data data = new ...
- JUC(1)线程和进程、并发和并行、线程的状态、lock锁、生产者和消费者问题
1.线程和进程 进程:一个程序,微信.qq...程序的集合.(一个进程包含多个线程,至少包含一个线程.java默认有两个线程:主线程(main).垃圾回收线程(GC) 线程:runnable.thre ...
- Lock锁与Condition监视器(生产者与消费者)。
/*生产者与消费者第二次敲,本人表示很郁闷,以后要经常读这个 * Condition 将Object类中的监视器(wait notify notifyAll)分解成不同的对象.例如condition_ ...
- 生产者消费者问题--synchronized
# 代码 public class App { public static void main(String[] args) { Depot depot = new Depot(100); Produ ...
随机推荐
- servelet 实现Post接口访问
先上代码: package com.jovtec.galaxy.mailbox; import java.io.BufferedReader; import java.io.IOException; ...
- Java排序算法(二)选择排序
一.测试类SortTest import java.util.Arrays; public class SortTest { private static final int L = 20; publ ...
- c++bind函数使用
总述 最近写代码的时候看到代码使用了bind,一个参数绑定的标准库函数.程序是这么写的, speaker_play_routine_ = new boost::thread (boost::b ...
- H - 看病要排队
看病要排队这个是地球人都知道的常识.不过经过细心的0068的观察,他发现了医院里排队还是有讲究的.0068所去的医院有三个医生(汗,这么少)同时看病.而看病的人病情有轻重,所以不能根据简单的先来先服务 ...
- 静态链表 Static Link List
Static Link List 静态链表 其中上图来自http://www.cnblogs.com/rookiefly/p/3447982.html 参考: http://www.cnblogs. ...
- Codeforces Round #647 (Div. 2) D. Johnny and Contribution(BFS)
题目链接:https://codeforces.com/contest/1362/problem/D 题意 有一个 $n$ 点 $m$ 边的图,每个结点有一个从 $1 \sim n$ 的指定数字,每个 ...
- Codeforces Round #540 (Div. 3) D2. Coffee and Coursework (Hard Version) (二分,贪心)
题意:有\(n\)个数,每次可以选\(k(1\le k\le n)\)个数,并且得到\(a_1+max(0,a_2-1)+max(0,a_3-2)+...+max(0,a_k-k+1)\)的贡献,问最 ...
- C#异步和多线程以及Thread、ThreadPool、Task区别和使用方法
本文的目的是为了让大家了解什么是异步?什么是多线程?如何实现多线程?对于当前C#当中三种实现多线程的方法如何实现和使用?什么情景下选用哪一技术更好? 第一部分主要介绍在C#中异步(async/awai ...
- httprunner(11)运行测试报告
前言 受益于pytest的集成,HttpRunner v3.x可以使用pytest所有插件,包括pytest-html和allure-pytest,也可以实现这2种方式的报告 内置html报告 pyt ...
- 在kubernetes集群里集成Apollo配置中心(5)之dubbo服务消费者连接apollo实战
1.在Apollo的portal创建dubbo消费者项目 (1)添加dubbo消费者项目 (2)在dubbo消费者项目中添加配置项 (3)发布 2.通过jenkins构建dubbo消费者镜像 3.登录 ...