生产者和消费者问题(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 ...
随机推荐
- 提供读取excel 的方法
/** * 对外提供读取excel 的方法 * */ public static List<List<Object>> readExcel(String path) throw ...
- Java帝国的成立
java帝国的成立 一场旷日持久的战争 1972年C语言诞生 贴近硬件 ,运行极快 , 效率极低 操作系统, 编译器 ,数据库, 网络系统 指针和内存 (容易犯错 , 暴力) 1982 年C++诞生 ...
- Could not transfer artifact org.apache.maven.plugins:maven-clean-plugin:pom:2.5 from 这类问题的解决方法
最近换了台电脑,所以重新在IEDA上搭建Spring Boot环境,遇到一个问题,网上查了很久,又实践了一通,终于解决,这里把步骤详细记录下来. 问题描述:创建IDEA的Maven项目后,出现 Mav ...
- P4587 [FJOI2016]神秘数(主席树)
题意:给出1e5个数 查询l,r区间内第一个不能被表示的数 比如1,2,4可以用子集的和表示出[1,7] 所以第一个不能被表示的是8 题解:先考虑暴力的做法 把这个区间内的数字按从小到大排序后 从前往 ...
- Pokémon Army (easy version) CodeForces - 1420C1 dp
题意: 给你一个长度为n个序列v,你需要从中找一个子序列.这个子序列的值等于:子序列中奇数下标的值-偶数下标的值 你需要使得这个值尽可能大,让你输出这个最大值 题解: dp[i][0]表示:在原序列从 ...
- zjnu1707 TOPOVI (map+模拟)
Description Mirko is a huge fan of chess and programming, but typical chess soon became boring for h ...
- Codeforces Round #653 (Div. 3) E1. Reading Books (easy version) (贪心,模拟)
题意:有\(n\)本书,A和B都至少要从喜欢的书里面读\(k\)本书,如果一本书两人都喜欢的话,那么他们就可以一起读来节省时间,问最少多长时间两人都能够读完\(k\)本书. 题解:我们可以分\(3\) ...
- Docker应用场景和局限性
Docker有哪些好的特性?作为一种新兴的虚拟化方式,Docker跟传统的虚拟化方式相比具有众多的优势.首先, Docker容器的启动可以在秒级实现,这相比传统的虚拟机方式要快得多.其次, Docke ...
- go免杀初探
0x01 go免杀 由于各种av的限制,我们在后门上线或者权限持久化时很容易被杀软查杀,容易引起目标的警觉同时暴露了自己的ip.尤其是对于windows目标,一个免杀的后门极为关键,如果后门文件落不了 ...
- centos7+腾讯云服务器搭建wordpress
title: centos7+腾讯云服务器搭建wordpress date: 2020-03-04 categories: web tags: [wordpress] 分两部分:1.搭建LEMP环境 ...