一文了解多线程实现交替执行

本文已收录于专栏
《Java》

背景介绍

  有一个需求是要求多个线程去执行任务,需要每个线程都执行一次之后再继续执行,也就是说每个线程交替去执行任务。举个例子来说,有两个线程,一个输出字母,一个输出数字。交替输出1A2B3C4D5E…来实现这样一个业务场景。
在这里插入图片描述

实现方式

  1. 使用LockSupport类中的unpark方法和park方法。unpark方法用来叫醒指定的线程,park方法用来将当前队列进入到阻塞的状态。
package com.example.threadpool.LockSupport;

import java.util.concurrent.locks.LockSupport;

/**
 * @BelongsProject: demo
 * @BelongsPackage: com.example.threadpool.LockSupport
 * @Author: Wuzilong
 * @Description: 使用LockSupport类中的park和unpark方法实现线程交替执行
 * @CreateTime: 2023-11-11 10:07
 * @Version: 1.0
 */

public class AlternatingExecution {
    private static Thread t1;
    private static Thread t2;
    public static void main(String[] args) {
        char[] oneArray="1234567".toCharArray();
        char[] twoArray="ABCDEFG".toCharArray();

         t1=new Thread(() ->{
            for (char one : oneArray){
                System.out.print(one);
                LockSupport.unpark(t2);//叫醒t2线程
                LockSupport.park();//阻塞当前线程
            }
        },"t1");

         t2 = new Thread(() ->{
            for (char two: twoArray){
                LockSupport.park();
                System.out.print(two);
                LockSupport.unpark(t1);
            }
        },"t2");

         t1.start();
         t2.start();
    }
}

运行结果
在这里插入图片描述

  1. 使用synchronized锁和notify方法和wait方法实现线程交替执行,notify方法事用来唤醒线程,wait方法是将当前的线程放到等待队列中等待执行,不允许执行其他的动作。
package com.example.threadpool.sync_notify_wait;
/**
 * @BelongsProject: demo
 * @BelongsPackage: com.example.threadpool.sync_notify_wait
 * @Author: Wuzilong
 * @Description: 使用synchronized锁住o对象,然后使用notify唤醒线程和wait去让线程等待
 * @CreateTime: 2023-11-11 14:25
 * @Version: 1.0
 */

public class Client {
    public static void main(String[] args) {
        Object o = new Object();

        char[] oneArray="123456".toCharArray();
        char[] twoArray="ABCDEF".toCharArray();

        new Thread(()->{
            synchronized (o){
                for (char one:oneArray){
                    System.out.print(one);
                    try{
                        o.notify();//唤醒线程
                        o.wait();//将线程放到等待队列中等待执行,不允许执行其他的动作
                    }catch ( Exception e){
                        e.printStackTrace();
                    }
                }
                o.notify();//必须添加,否则无法停止程序
            }
        },"t1").start();



        new Thread(()->{
            synchronized (o){
                for(char two:twoArray){
                    System.out.print(two);
                    try{
                        o.notify();
                        o.wait();
                    }catch (Exception e){
                        e.printStackTrace();
                    }
                }
                o.notify();
            }
        },"t2").start();
    }


}

运行结果
在这里插入图片描述

  1. 使用Lock锁和condition的signal方法和await方法实现多线程之间交替执行,signal方法用来唤醒其他线程,await方法用来将当前线程进入阻塞队列。
package com.example.threadpool.lock_condition;

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

/**
 * @BelongsProject: demo
 * @BelongsPackage: com.example.threadpool.lock_condition
 * @Author: Wuzilong
 * @Description: 描述什么人干什么事儿
 * @CreateTime: 2023-11-11 15:39
 * @Version: 1.0
 */

public class Client {
    public static void main(String[] args) {
        char oneArray[]="123456".toCharArray();
        char twoArray[]="ABCDEF".toCharArray();

        Lock lock=new ReentrantLock();
        Condition condition = lock.newCondition();

        new Thread(()->{
            lock.lock();
            try{
                for (char one: oneArray){
                    System.out.println(one);
                    condition.signal();  //唤醒其他线程
                    condition.await(); //当前线程进入阻塞队列
                }
            }catch (Exception e){
                e.printStackTrace();
            }finally {
                lock.unlock();
            }
        },"t1").start();

        new Thread(()->{
            lock.lock();
            try{
                for (char two:twoArray){
                    System.out.println(two);
                    condition.signal();
                    condition.await();
                }
            }catch (Exception e){
                e.printStackTrace();
            }finally {
                lock.unlock();
            }
        },"t2").start();
    }
}

运行结果
在这里插入图片描述

  1. 使用LinkedTransferQueue队列中的take方法和transfer方法实现多个线程交替执行,transfer方法是向队列中添加内容,添加的内容如果没有被使用是不会执行下面的代码逻辑的,take方法是从队列中获取内容。
package com.example.threadpool.TransferQueue;

import java.util.concurrent.LinkedTransferQueue;
import java.util.concurrent.TransferQueue;

/**
 * @BelongsProject: demo
 * @BelongsPackage: com.example.threadpool.TransferQueue
 * @Author: Wuzilong
 * @Description: 描述什么人干什么事儿
 * @CreateTime: 2023-11-11 16:39
 * @Version: 1.0
 */

public class Client {
    public static void main(String[] args) {
        char[] oneArray="123456".toCharArray();
        char[] twoArray="ABCDEF".toCharArray();
        //声明一个队列
        TransferQueue<Character> queue=new LinkedTransferQueue<>();
        new Thread(()->{
            try{
                for (char one:oneArray){
                    System.out.print(queue.take()); //从队列中获取内容
                    queue.transfer(one);
                }
            }catch (Exception e){
                e.printStackTrace();
            }
        },"t1").start();


        new Thread(()->{
            try{
                for(char two :twoArray){
                    queue.transfer(two); //向队列中添加内容,添加的内容如果没有被拿走是不会执行下面的代码逻辑的。
                    System.out.print(queue.take());
                }
            }catch (Exception e){
                e.printStackTrace();
            }
        },"t2").start();
    }
}

运行效果
在这里插入图片描述

总结提升

  对于一个需求的实现方式有很多种,我们可以通过不同的维度,针对于业务的侧重点不同来由不同的实现方式,我们要有无限的思想去思考问题,要有发展的眼光去看待问题。


🎯 此文章对你有用的话记得留言+点赞+收藏哦🎯
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

武梓龙_Wzill

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

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

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

打赏作者

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

抵扣说明:

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

余额充值