生产者和消费者问题(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 ...
随机推荐
- cassandra权威指南读书笔记--安全
认证和授权driver,JMX和cassandra服务器支持SSL/TLS,cassandra节点间也支持SSL/TLS.密码认证器cassandra还支持自定义,可插拔的认证机制.默认的认证器:or ...
- Flink-v1.12官方网站翻译-P012-Stateful Stream Processing
有状态的流处理 什么是状态? 虽然数据流中的许多操作一次只看一个单独的事件(例如事件解析器),但有些操作会记住多个事件的信息(例如窗口操作符).这些操作被称为有状态操作.一些有状态操作的例子. - 当 ...
- HDU-6599 I Love Palindrome String(回文自动机+字符串hash)
题目链接 题意:给定一个字符串\(|S|\le 3\times 10^5\) 对于每个 \(i\in [1,|S|]\) 求有多少子串\(s_ls_{l+1}\cdots s_r\)满足下面条件 \( ...
- HDU - 2328 Corporate Identity(kmp+暴力)
传送门:http://acm.hdu.edu.cn/showproblem.php?pid=2328 题意:多组输入,n==0结束.给出n个字符串,求最长公共子串,长度相等则求字典序最小. 题解:(居 ...
- gym100923C. Por Costel and Bujor (高斯消元)
题意:简化一下 就是解N个 系数矩阵一样 等式右边列矩阵不一样的方程组 题解:系数矩阵一样 为什么我却毫无办法???? 其实只要把等式右边的矩阵都排在后面就好了啊 就变成解一个N x 2N的方程组了 ...
- c语言实现--双向循环链表操作
1,双向链表相当于两个单向循环链表. 2,双向链表的结点定义. 1 struct DULNode 2 { 3 int data; 4 struct DULNode * prior; 5 struct ...
- Educational Codeforces Round 96 (Rated for Div. 2) E. String Reversal (思维,逆序对)
题意:给你一个字符串,每次可以调换现字符串的相邻两个字符,问最少操作多少次使得这个字符串等于其反转过来的字符串. 题解:先考虑字符串中没有相同字符的情况,那么我们每次将目前字符串的最后一个字符一直调换 ...
- MySQL中为避免索引失效所需注意的问题
一.索引介绍 二.索引的优势与劣势 1.优势 类似于书籍的目录索引,提高数据检索的效率,降低数据库的IO成本. 通过索引列对数据进行排序,降低数据排序的成本,降低CPU的消耗. 2.劣势 实际上索引也 ...
- 洛谷P2241-统计方形-矩形内计算长方形和正方形的数量
洛谷P2241-统计方形 题目描述: 有一个 \(n \times m\) 方格的棋盘,求其方格包含多少正方形.长方形(不包含正方形). 思路: 所有方形的个数=正方形的个数+长方形的个数.对于任意一 ...
- 在kubernetes集群里集成Apollo配置中心(4)之dubbo服务提供者连接apollo实战
1.登录portal.od.com(Apollo-portal),新建一个dubbo-demo-service项目 2.在Apollo项目中的dubbo-demo-service添加配置 (1)添加d ...