09-Condition实现精准通知唤醒

package com.hkx.pc;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @program: juc
 * @description: 09-Condition实现精准通知唤醒
 * @author: Casey Hu
 * @create: 2022-08-14 19:51
 **/

/**
 * A执行完,调用B。B执行完,调用C。C执行完,调用A。
 */
public class C {
    public static void main(String[] args) {
        Data3 data3=new Data3();
        new Thread(()->{
            for (int i=0;i<10;i++){
                data3.printA();
            }
        },"A").start();
        new Thread(()->{
            for (int i=0;i<10;i++){
                data3.printB();
            }
        },"B").start();
        new Thread(()->{
            for (int i=0;i<10;i++){
                data3.printC();
            }
        },"C").start();
    }
}
class Data3{

    private Lock lock=new ReentrantLock();
    private Condition condition1 = lock.newCondition();
    private Condition condition2 = lock.newCondition();
    private Condition condition3 = lock.newCondition();
    private int num=1;
    public void printA(){
        lock.lock();
        try {
            //业务——>判断——>执行——>通知
            while(1!=num){
                condition1.await();
            }
            System.out.println(Thread.currentThread().getName()+"=>AAAAA");
            num=2;
            //唤醒指定的人 B
            condition2.signal();
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            lock.unlock();
        }
    }
    public void printB(){
        lock.lock();
        try {
            //业务——>判断——>执行——>通知
            while (2!=num){
                condition2.await();
            }
            System.out.println(Thread.currentThread().getName()+"=>BBBBB");
            num=3;
            //唤醒指定的人 C
            condition3.signal();
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            lock.unlock();
        }
    }
    public void printC(){
        lock.lock();
        try {
            //业务——>判断——>执行——>通知
            while(num!=3){
                condition3.await();
            }
            System.out.println(Thread.currentThread().getName()+"=>CCCCC");
            num=1;
            //唤醒指定的人 A
            condition1.signal();
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            lock.unlock();
        }
    }
}

上面的代码主要设置了多个监视器,随时唤醒指定的线程。
购物场景:在下单完成之后,调用支付操作,在支付完成之后调用交易完成页面,在交易完成之后调用物流操作

5、8锁现象

如何判断锁是谁,永远知道什么是锁,锁到底锁的是谁!
深刻理解锁是什么

package com.hkx.lock8;

/**
 * @program: juc
 * @description:
 * @author: Casey Hu
 * @create: 2022-08-21 20:14
 **/

import java.util.concurrent.TimeUnit;

/***
 *
 *8锁,就是关于锁的8个问题
 * 1、在标准情况下,两个线程是先打印哪个呢? 1发短信 2打电话
 * 2、发短信的方法延迟四秒,两个线程是先打印哪个呢? 1发短信 2打电话
 */

public class Test1 {
    public static void main(String[] args) {
        Phone phone=new Phone();
        new Thread(()->{
            phone.sendSms();
        },"A").start();
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        new Thread(()->{
            phone.call();
        },"B").start();
    }
}
class Phone{
    //被synchronized修饰的方法,锁的是方法的调用者
    //两个方法用的是同一把锁phone的锁,哪个方法先拿到就先执行哪个
    public synchronized void sendSms(){
        try {
            TimeUnit.SECONDS.sleep(4);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        System.out.println("发短信");
    }
    public synchronized void call(){
        System.out.println("打电话");
    }
}


package com.hkx.lock8;

import java.util.concurrent.TimeUnit;

/**
 * @program: juc
 * @description:
 * @author: Casey Hu
 * @create: 2022-08-21 21:15
 **/

/**
 * 3、曾加了一个普通方法,是先执行发短信还是执行hello?  hello 发短信 1秒钟输出hello,四秒中说出发短信
 * 4、两个对象,都执行同步方法  是先执行哪个?
 */
public class Test2  {
    public static void main(String[] args) {
        //两个对象,两个调用者,两把锁
        Phone2 phone1=new Phone2();
        Phone2 phone2=new Phone2();
        new Thread(()->{
            phone1.sendSms();
        },"A").start();
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        new Thread(()->{
            phone2.call();
        },"B").start();
    }
}
class Phone2{
    //被synchronized修饰的方法,锁的是方法的调用者
    //两个方法用的是同一把锁phone的锁,哪个方法先拿到就先执行哪个
    public synchronized void sendSms(){
        try {
            TimeUnit.SECONDS.sleep(4);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        System.out.println("发短信");
    }
    public synchronized void call(){
        System.out.println("打电话");
    }
    //没有锁,不受锁的影响
    public void hello(){
        System.out.println("hello");
    }
}
package com.hkx.lock8;

import java.util.concurrent.TimeUnit;

/**
 * @program: juc
 * @description:
 * @author: Casey Hu
 * @create: 2022-08-21 21:32
 **/

/***
 * 5.增加两个静态同步方法,只有一个对象,是先打印哪个? 发短信 打电话
 * 6、两个对象,增加两个静态同步方法,是先打印哪个? 发短信 打电话
 */

public class Test3  {
    public static void main(String[] args) {
        //两个对象,锁的模板只有一个,
        Phone3 phone1 =new Phone3();
        Phone3 phone2 =new Phone3();
        new Thread(()->{
            phone1.sendSms();
        },"A").start();
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        new Thread(()->{
            phone2.call();
        },"B").start();
    }
}
//5、Phone3 只有唯一 的Class对象,static锁的是class
//6、两个对象,增加两个同步方法,是先打印,还是先发短信,打电话。
class Phone3{
    //被synchronized修饰的方法,锁的是方法的调用者
    //static 静态方法,在类一加载就有了! Class 模板
    public static synchronized void sendSms(){
        try {
            TimeUnit.SECONDS.sleep(4);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        System.out.println("发短信");
    }
    public static synchronized void call(){
        System.out.println("打电话");
    }
}
package com.hkx.lock8;

import java.util.concurrent.TimeUnit;

/**
 * @program: juc
 * @description:
 * @author: Casey Hu
 * @create: 2022-08-21 21:51
 **/

/**
 * 7、一个对象,一个静态同步方法,一个普通同步方法,是先打印哪个? 打电话 发短信
 * 7、两个对象,一个静态同步方法,一个普通同步方法,是先打印哪个? 打电话 发短信
 */
public class Test4  {
    public static void main(String[] args) {
        //两个对象,锁的模板只有一个,
        Phone4 phone1 =new Phone4();
        Phone4 phone2 =new Phone4();
        new Thread(()->{
            phone1.sendSms();
        },"A").start();
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        new Thread(()->{
            phone2.call();
        },"B").start();
    }
}
//5、Phone3 只有唯一 的Class对象,static锁的是class
//6、两个对象,增加两个同步方法,是先打印,还是先发短信,打电话。
class Phone4{
    //static 静态方法,在类一加载就有了!锁的是Class 模板
    public static synchronized void sendSms(){
        try {
            TimeUnit.SECONDS.sleep(4);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        System.out.println("发短信");
    }
    //被synchronized修饰的方法,锁的是方法的调用者
    public  synchronized void call(){
        System.out.println("打电话");
    }
}

小结

到底锁,锁的是啥? new出来的,static修饰的
new this 具体的一个
static Class 唯一的一个模板

6、集合类不安全

List

package com.hkx.unsafe;
import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;
/**
 * @program: juc
 * @description: 集合类不安全_List
 * @author: Casey Hu
 * @create: 2022-09-18 17:39
 **/
// java.util.ConcurrentModificationException 并发修改异常
public class ListTest {
    public static void main(String[] args) {
        //并发下 ArrayList 是不安全的
        /**
         * 解决方案:
         * 1.List<String> list = new Vector<>();
         * 2.由于ArrayList 不安全,我们选择使用工具类的转化,让ArrayList 变得安全
         * List<String> list = Collections.synchronizedList(new ArrayList<>());
         * 3.List<String> list =new   CopyOnWriteArrayList<String>();
         * CopyOnWrite 写入时候复制 COW 是计算机程序设计领域的一直优化策略
         *多个线程调用的时候,比如唯一的list 在读取的时候是固定的,写入的时候会出现,覆盖的情况
         * 在写的入的时候避免覆盖造成数据问题,造成数据问题
         * 注意:CopyOnWriteArrayList 比 Vector 强在哪?
         * 就是在 CopyOnWriteArrayList 没有 synchronized 修饰采用的 是复制一份在重新赋值的逻辑
         * Vector 里有synchronized 修饰 效率会很低
         */
//        List<String> list = new Vector<>();
//        List<String> list = Collections.synchronizedList(new ArrayList<>());
        List<String> list =new   CopyOnWriteArrayList<String>();
        for (int i=1;i<=10;i++){
            new Thread(()->{
                list.add(UUID.randomUUID().toString().substring(0,5));
                System.out.println(list);
            },String.valueOf(i)).start();
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Casey·Hu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值