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)的更多相关文章

  1. 第44天学习打卡(JUC 线程和进程 并发和并行 Lock锁 生产者和消费者问题 如何判断锁(8锁问题) 集合类不安全)

    什么是JUC 1.java.util工具包 包 分类 业务:普通的线程代码 Thread Runnable 没有返回值.效率相比Callable相对较低 2.线程和进程 进程:一个程序.QQ.exe, ...

  2. Java 多线程之生产者消费者(多个生成者多个消费者)synchronized 和lock多线程通讯和同步实现

    public class ProducterConsumerSample { public static void main(String[] args) { Resourse res = new R ...

  3. JAVA基础再回首(二十五)——Lock锁的使用、死锁问题、多线程生产者和消费者、线程池、匿名内部类使用多线程、定时器、面试题

    JAVA基础再回首(二十五)--Lock锁的使用.死锁问题.多线程生产者和消费者.线程池.匿名内部类使用多线程.定时器.面试题 版权声明:转载必须注明本文转自程序猿杜鹏程的博客:http://blog ...

  4. 多生产者多消费者(第一种方式),基于synchronized,wait,notifyAll

    生产者消费者模式描述的是协调与协作关系.比如一个人正在准备食物(生产者),而另一个人正在吃(消费者),他们使用一个共用 的桌子用于放置盘子和取走盘子,生产者准备食物,如果桌子上已经满了就等待,消费者( ...

  5. 同步锁Lock & 生产者和消费者案例

    显示锁 Lock ①在 Java 5.0 之前,协调共享对象的访问时可以使用的机 制只有 synchronized 和 volatile . Java 5.0 后增加了一些 新的机制,但并不是一种替代 ...

  6. JUC 并发编程--02,生产者和消费者 synchronized的写法 , juc的写法. Condition的用法

    synchronized的写法 class PCdemo{ public static void main(String[] args) { //多个线程操作同一资源 Data data = new ...

  7. JUC(1)线程和进程、并发和并行、线程的状态、lock锁、生产者和消费者问题

    1.线程和进程 进程:一个程序,微信.qq...程序的集合.(一个进程包含多个线程,至少包含一个线程.java默认有两个线程:主线程(main).垃圾回收线程(GC) 线程:runnable.thre ...

  8. Lock锁与Condition监视器(生产者与消费者)。

    /*生产者与消费者第二次敲,本人表示很郁闷,以后要经常读这个 * Condition 将Object类中的监视器(wait notify notifyAll)分解成不同的对象.例如condition_ ...

  9. 生产者消费者问题--synchronized

    # 代码 public class App { public static void main(String[] args) { Depot depot = new Depot(100); Produ ...

随机推荐

  1. k8s command & args

    命令和参数说明: command.args两项实现覆盖Dockerfile中ENTRYPOINT的功能,具体的command命令代替ENTRYPOINT的命令行,args代表集体的参数. 如果comm ...

  2. (13)Linux文件系统的优缺点

    通过文件系统的方式来组织磁盘存储和数据管理.有以下几个方面的好处. 数据的读取.管理操作变得简单 文件系统给用户提供了一个简单的操作界面,用户可以通过对文件系统的简单操作,实现对磁盘的管理.虽然 Li ...

  3. Jenkins(4)docker容器内部修改jenkins容器时间

    前言 用docker搭建的Jenkins环境时间显示和我们本地时间相差8个小时,需修改容器内部的系统时间 查看时间 查看系统时间 date-R 进入docker容器内部,查看容器时间 docker e ...

  4. FatMouse and CheeseI - I

    FatMouse has stored some cheese in a city. The city can be considered as a square grid of dimension ...

  5. 2017-2018 ACM-ICPC, Asia Daejeon Regional Contest PART(10/12)

    $$2017-2018\ ACM-ICPC,\ Asia\ Daejeon\ Regional\ Contest$$ \(A.Broadcast\ Stations\) \(B.Connect3\) ...

  6. poj 3304 Segments(解题报告)

    收获:举一反三:刷一道会一道 1:思路转化:(看的kuangbin的思路) 首先是在二维平面中:如果有很多线段能够映射到这个直线上并且至少重合于一点,充要条件: 是过这个点的此条直线的垂线与其他所有直 ...

  7. hdu 6806 Equal Sentences 找规律

    题意: 给你一个有n个单词的单词串S,对这n个单词进行排列组合形成新的一个单词串T,如果在S中任意某个单词所在位置,和这个单词在T中所在位置之差的绝对值小于等于1,那么就说S和T串相等 让你求S一共有 ...

  8. hdu1004 Let the Balloon Rise

    Problem Description Contest time again! How excited it is to see balloons floating around. But to te ...

  9. centos 7下安装配置Supervisor

    1.安装Supervisor centos下安装yum install supervisor 2. systemctl enable supervisord 开机自启 systemctl start ...

  10. 通过修改etcd来设置或修改节点flannel子网信息

    在首次启动flannel服务的时候可以手动指定subnet.env文件,配置所在节点的flannel子网网段,如果不指定配置文件,flannel将自动分配一个子网网段并生成配置文件 /var/run/ ...