Java-线程交替

java 多线程交替

要求:

甲线程:a、b、c、d、e
乙线程:1、2、3、4、5
丙线程:A、B、C、D、E

输出结果:a-1-A b-2-B c-3-C …

方法1:

在临界区使用一个数字代表当前执行的线程号,线程每打印一个字符就切换为下一个线程号

/**
 * 3线程交替打印字符
 * 注:每次当前线程打印完一个字符,就切换到下一个线程
 * @author a_apple
 * @create 2020-05-06 21:32
 */
class Resource {

    private int current = 1;

    /**
     * 
     * 如果当前线程号 now!=current   -->阻塞
     *         否则  current = next -->切换下一次应该执行的线程号
     * @param now  用来代表当前的执行线程
     * @param next 用来代表下一个要执行的线程
     */
    public void changeCurrent(int now, int next) {
        //changeCurrent(1,2),三个线程交替的流程顺序
        //changeCurrent(2,3),
        //changeCurrent(3,1),
        while (current != now) {
            try {
                wait();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        //如果等于当前线程,那么执行完切换下一个
        current = next;
        notifyAll();
    }
}

class SubThread implements Runnable {

    private final Resource res;
    private char[] arr;
    private int now;
    private int next;
    private Thread t1;

    /**
     * 通过传参告知线程的执行顺序
     *
     * @param res  临界资源
     * @param arr  需要被打印的字符数组
     * @param now  当前要执行的线程(自身Demo对象
     * @param next 下一个要执行的线程
     */
    public SubThread(Resource res, char[] arr, int now, int next) {
        this.res = res;
        this.arr = arr;
        this.now = now;
        this.next = next;
        t1 = new Thread(this);
    }

    @Override
    public void run() {
        //获取对象锁
        synchronized (res) {
            for (char c1 : arr) {
                //切换下一个线程,并唤醒所有
                //注意,不能打印后再切换,因为当前对象锁还没放,会继续打印2后,当前线程才阻塞。此时输出:1-2-a-
                res.changeCurrent(now, next);

                System.out.print(c1 + "-");
                if(c1>='a')
                    System.out.println();
                try {
                    //当前线程暂停0.5秒,但未放锁res
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public void start() {
        t1.start();
    }

    public void join() throws InterruptedException {
        t1.join();
    }
}

public class ThreadDemo {

    public static void main(String[] args) throws Exception {

        char[] c1 = {'1', '2', '3', '4', '5'};
        char[] c2 = {'A', 'B', 'C', 'D', 'E'};
        char[] c3 = {'a', 'b', 'c', 'd', 'e'};

        //临界资源,初始
        Resource res = new Resource();

        SubThread t1 = new SubThread(res, c1, 1, 2);
        SubThread t2 = new SubThread(res, c2, 2, 3);
        SubThread t3 = new SubThread(res, c3, 3, 1);

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

输出:

1-A-a-
2-B-b-
3-C-c-
4-D-d-
5-E-e-
方法2:

使用Lock配合Condition实现精准唤醒,使线程有序进行

package pers.xu.multithread.question;

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

/**
 * 使用精准唤醒打印交替打印字符
 * @author a_apple
 * @create 2020-05-25 9:09
 */

class PrintStore{

    private Lock lock = new ReentrantLock();
    private int num = 1;

    Condition conditionA = lock.newCondition();
    Condition conditionB = lock.newCondition();
    Condition conditionC = lock.newCondition();

    public void printA(char ch){
        lock.lock();
        try {
            if(num!=1){
                conditionA.await();
            }
            System.out.print(ch+"-");
            // 换标志唤醒B
            num = 2;
            conditionB.signal();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    public void printB(char ch){
        lock.lock();
        try {
            if(num!=2){
                conditionB.await();
            }
            System.out.print(ch+"-");
            // 换标志唤醒C
            num = 3;
            conditionC.signal();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    public void printC(char ch){
        lock.lock();
        try {
            if(num!=3){
                conditionC.await();
            }
            System.out.print(ch+"\n");
            // 换标志唤醒B
            num = 1;
            conditionA.signal();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }
}

public class AlterPrint {

    public static void main(String[] args){

        PrintStore store = new PrintStore();

        char[] arrA = {'a','b','c','d','e'};
        char[] arrB = {'1','2','3','4','5'};
        char[] arrC = {'A','B','C','D','E'};

        new Thread(()->{
            for (int i = 0; i < arrA.length; i++) {
                store.printA(arrA[i]);
            }
        }).start();

        new Thread(()->{
            for (int i = 0; i < arrB.length; i++) {
                store.printB(arrB[i]);
            }
        }).start();

        new Thread(()->{
            for (int i = 0; i < arrC.length; i++) {
                store.printC(arrC[i]);
            }
        }).start();
    }
}

输出:

a-1-A
b-2-B
c-3-C
d-4-D
e-5-E
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值