Skip to content

线程运行顺序控制

固定运行顺序

先让线程2执行,然后线程1再执行

wait+notify

public class Test1 {

    private static final Object lock = new Object();

    // 表示 t2 是否运行过
    private static boolean t2Runned = false;


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

        Thread t1 = new Thread(() ->{
            // 如果 t2 没有运行过, 需要等待
            synchronized (lock){
                while (!t2Runned){
                    try {
                        lock.wait();
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                }
            }

            log.info("1");
        }, "t1");

        Thread t2 = new Thread(() ->{
            synchronized (lock){
                log.info("2");
                // 运行结束之后通知其他线程
                t2Runned = true;
                lock.notify();
            }

        }, "t2");

        log.info("t1 开始运行");
        t1.start();
        Thread.sleep(1000L);
        t2.start();
    }
}

await+signal

public class Test2 {

    private static ReentrantLock lock = new ReentrantLock();
    private static Condition condition = lock.newCondition();

    // 表示 t2 是否运行过
    private static boolean t2Runned = false;

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

        Thread t1 = new Thread(() ->{
            lock.lock();
            try{
                while (!t2Runned){
                    condition.await();
                }
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            } finally {
                lock.unlock();
            }


            log.info("1");
        }, "t1");

        Thread t2 = new Thread(() ->{
            lock.lock();
            try{
                log.info("2");
                // 运行结束之后通知其他线程
                t2Runned = true;
                condition.signal();
            } finally {
                lock.unlock();
            }

        }, "t2");

        log.info("t1 开始运行");
        t1.start();
        Thread.sleep(1000L);
        t2.start();
    }
}

交替输出

交替打印A、B、C

wait+notify

使用一个标记,1打印A,2打印B,3打印C

输出内容    等待标记    下一个标记
A           1           2
B           2           3
C           3           1
public class Test3 {

    public static void main(String[] args) {

        WaitNotify waitNotify = new WaitNotify(1, 100);

        Thread t1 = new Thread(() -> {
            waitNotify.print("A", 1, 2);
        }, "t1");

        Thread t2 = new Thread(() -> {
            waitNotify.print("B", 2, 3);
        }, "t2");

        Thread t3 = new Thread(() -> {
            waitNotify.print("C", 3, 1);
        }, "t3");

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

    }
}

class WaitNotify{
    private int flag;// 等待标记
    private int loopNumber;// 循环次数

    public WaitNotify(int flag, int loopNumber) {
        this.flag = flag;
        this.loopNumber = loopNumber;
    }

    public void print(String str, int waitFlag, int nextFlag) {
        for (int i = 0; i < loopNumber; i++) {
            synchronized (this){
                while (flag != waitFlag){
                    try {
                        this.wait();
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                }
                System.out.print(str);
                flag = nextFlag;
                // 唤醒其他线程
                this.notifyAll();
            }
        }
    }
}

await+signal

public class Test4 {

    public static void main(String[] args) throws InterruptedException {
        AwaitSignal awaitSignal = new AwaitSignal(10);

        Condition a = awaitSignal.newCondition();
        Condition b = awaitSignal.newCondition();
        Condition c = awaitSignal.newCondition();

        new Thread(() -> {
            awaitSignal.print("A", a, b);
        }, "t1").start();

        new Thread(() -> {
            awaitSignal.print("B", b, c);
        }, "t2").start();

        new Thread(() -> {
            awaitSignal.print("C", c, a);
        }, "t3").start();


        // 需要主线程唤醒 a
        Thread.sleep(1000);
        awaitSignal.lock();
        try {
            System.out.println("开始执行...");
            a.signal();
        }
        finally {
            awaitSignal.unlock();
        }

    }
}


class AwaitSignal extends ReentrantLock{
    private int loopNumber;

    public AwaitSignal(int loopNumber) {
        this.loopNumber = loopNumber;
    }

    /**
     * 交替打印
     * @param str 需要打印的字符
     * @param cur 需要进那间休息室
     * @param next 打印完通知的休息室
     */
    public void print(String str, Condition cur, Condition next){
        for (int i = 0; i < loopNumber; i++) {
            lock();
            try {
                // 都先等待, 直到被唤醒
                cur.await();
                // 开始干活
                System.out.print(str);
                // 通知下一个休息室
                next.signal();
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            } finally {
                unlock();
            }
        }
    }
}