我看谁还不懂多线程之间的通信+基础入门+实战教程+详细介绍+附源

2022-11-07  本文已影响0人  Kyriez7

一、多线程之间的通信(Java版本)

1、多线程概念介绍

多线程概念

2、线程之间如何通信

引入

Java 线程通信的方式

3、线程通信方法详细介绍

主要介绍wait/notify,也有ReentrantLock的Condition条件变量的await/signal,LockSupport的park/unpark方法,也能实现线程之间的通信。主要是阻塞/唤醒通信模式。

首先说明这种方法一般都是作用于调用方法的所在线程。比如在主线程执行wait方法,就是将主线程阻塞了。

wait/notify机制

await/signal

park/unpark

回到目录

二、线程通信过程中需要注意的问题

1、唤醒丢失

如果一个线程先于被通知线程调用wait()前调用了notify(),等待的线程将错过这个信号。

核心代码演示

        // 线程一使用LOCK1对象调用wait方法阻塞自己        executor.execute(new ThreadTest("线程一",LOCK1,LOCK2));         synchronized (LOCK1) {            System.out.println("main执行notify方法让线程一醒过来");            LOCK1.notify();        }

2、假唤醒

由于莫名其妙的原因,线程有可能在没有调用过notify()和notifyAll()的情况下醒来。

3、多线程唤醒

        synchronized (waitName) {            while (!flag.getFlag()) {                try {                    // 将标志位设置为TRUE                    flag.setFlag(Constants.WaitOrNoWait.WAIT.getFlag());                    System.out.println("name;"+name+" 我睡着了进入阻塞状态" + "flag = " + flag.getFlag());                    waitName.wait();                    System.out.println("name;"+name+" 我醒来了" + "flag = " + flag.getFlag());                } catch (InterruptedException e) {                    e.printStackTrace();                }            }        }
    private final static Object LOCK1 = new Object();    private final static Object LOCK2 = new Object();    private final  static Constants.WaitStatus FLAG = new Constants.WaitStatus(false);    public static void main(String[] args) throws InterruptedException {        ThreadPoolExecutor executor = new ThreadPoolExecutor(2, 5, 1, TimeUnit.DAYS, new ArrayBlockingQueue<>(4), new ThreadPoolExecutor.AbortPolicy());        executor.execute(new ThreadTest("线程一",LOCK1,LOCK2, FLAG));        // ···唤醒    } class ThreadTest implements Runnable { //阻塞··· }

完整代码可以看这[Gitee仓库完整代码][https://gitee.com/malongfeistudy/javabase/tree/master/Java多线程_Study/src/main/java/com/mlf/thread/demo_wait_notify]

回到目录

三、线程通信实战

前置知识:线程池的使用方法

    /**     * 每个使用对应唯一的对象作为监视器对象锁。     */    public static final Object A_O = new Object();    public static final Object B_O = new Object();         /** 参数:         * int corePoolSize,                     核心线程数         * int maximumPoolSize,                  最大线程数         * long keepAliveTime,                   救急存活时间         * TimeUnit unit,                        单时间位         * BlockingQueue<Runnable> workQueue,    阻塞队列         * RejectedExecutionHandler handler      拒绝策略         **/        // 使用阿里巴巴推荐的创建线程池的方式        // 通过ThreadPoolExecutor构造函数自定义参数创建        ThreadPoolExecutor executor = new ThreadPoolExecutor(                3,                5,                1,                TimeUnit.DAYS,                new ArrayBlockingQueue<>(2),                new ThreadPoolExecutor.AbortPolicy());
class ThreadDiy implements Runnable {     private final String name;     /**     * 阻塞锁对象  等待标记     **/    private final Object waitFor;     /**     * 执行锁对象  下一个标记     **/    private final Object next;     public AlternateThread(String name, Object waitFor, Object next) {    }     @Override    public void run() {        // 线程的代码逻辑···    } } 

1、控制两个线程之间的执行顺序

题目:现在有两个线程,不论线程的启动顺序,我需要指定线程一先执行,然后线程二再执行。

        // 使用线程池创建线程        executor.execute(new DiyThread(1, ONE_LOCK, TWO_LOCK));        executor.execute(new DiyThread(2, TWO_LOCK, ONE_LOCK));         synchronized (ONE_LOCK) {            ONE_LOCK.notify();        }

创建线程类

2、多线程交替打印输出

题目需求:现在需要使用三个线程轮流打印输出。说白了也就是多线程轮流执行罢了,和问题一控制两个线程打印顺序没什么区别

    /**     * 阻塞锁对象  等待标记     **/    private final Object waitFor;    /**     * 唤醒锁对象  下一个标记     **/    private final Object next;
/** * 模拟执行流程 * 打印名(name)    等待标记(waitFor)   下一个标记(next) *      1                 A                  B *      2                 B                  C *      3                 C                  A *  * 像不像Spring的循环依赖:确实很像,Spring中的循环依赖就是 BeanA 依赖 BeanB,BeanB 依赖 BeanA; * 他们实例化过程中都需要先属性注入对方的实例,倘若刚开始的时候都没有实例化,初始化就会死等。类似于死锁。 **/

3、多线程顺序打印同一个自增变量

使用多线程轮流打印 01234····

具体代码请移步到Gitee仓库:[顺序打印自增变量][https://gitee.com/malongfeistudy/javabase/blob/master/Java多线程_Study/src/main/java/com/mlf/thread/print/AddNumberPrint2.java]

条件变量Condition的使用

上一篇下一篇

猜你喜欢

热点阅读