09-Condition realizes accurate notification wake-up

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();
        }
    }
}

The above code mainly sets up multiple monitors and wakes up the specified thread at any time.
Shopping scenario: call the payment operation after the order is placed, call the transaction completion page after the payment is completed, and call the logistics operation after the transaction is completed

5. 8-lock phenomenon

How to judge who the lock is, always know what the lock is, and who the lock is!
A deep understanding of what a lock is

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("打电话");
    }
}

summary

What is the lock? From new, statically modified
new this is a specific
static Class and the only template

6. The collection class is not safe

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();
        }
    }
}

Guess you like

Origin blog.csdn.net/qq_43658218/article/details/126335718