如何控制多线程的顺序执行

并发编程的重点:多线程之间的同步,依赖synchornized,wait & notify,AQS和基于Lock的各种实现。
9种方法实现多线程的顺序执行,定义thread1、thread2、thread3,要求执行顺序为:thread1 > thread2 > thread3

1 使用线程的join方法

线程依次join前序执行的线程;

    Thread thread1 = new Thread(
            () -> {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("thread1 finished");
            }
    );
    Thread thread2 = new Thread(
            () -> {
                try {
                    thread1.join();
                    Thread.sleep(1000);
                    System.out.println("thread2 finished");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
    );
    Thread thread3 = new Thread(
            () -> {
                try {
                    thread2.join();
                    System.out.println("thread3 finished");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
    );
    thread3.start();
    thread2.start();
    thread1.start();

2 使用主线程的join方法

        Thread thread1 = new Thread(
                () -> {
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("thread1 finished");
                }
        );
        Thread thread2 = new Thread(
                () -> {
                    try {
                        thread1.join();
                        Thread.sleep(1000);
                        System.out.println("thread2 finished");
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
        );
        Thread thread3 = new Thread(
                () -> {
                    try {
                        thread2.join();
                        System.out.println("thread3 finished");
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
        );
        thread1.start();
        thread1.join();
        thread2.start();
        thread2.join();
        thread3.start();
        thread3.join();

3 使用对象的wait和notify方法

设置锁对象:lock
设置线程的执行状态:state

thread1、thread2、thread3竞争lock;
如果thread2先获得lock,判断thread1是否已经执行完毕,如果thread1没有执行完毕,那么thread2 wait,如果thread1已经执行完毕,thread2可以执行。
如果thread3先获得lock,判断thread2是否已经执行完毕,如果thread2没有执行完毕,那么thread3 wait,如果thread2已经执行完毕,thread3可以执行。
thread1执行完毕后,唤醒thread2和thread3。

Object lock = new Object();
AtomicInteger state = new AtomicInteger(0);

Thread thread1 = new Thread(
    () -> {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        synchronized (lock) {
            System.out.println("thread1 got lock");
            System.out.println("thread1 finished");
            state.addAndGet(1);
            lock.notifyAll();
        }
    }
);

Thread thread2 = new Thread(
    () -> {
        synchronized (lock) {
            System.out.println("thread2 got lock");
            while (state.get() < 1) {
                try {
                    System.out.println("thread2 waiting");
                    lock.wait();
                    System.out.println("thread2 wakeup");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println("thread2 finished");
            state.addAndGet(1);
            lock.notifyAll();
        }
    }
);

Thread thread3 = new Thread(
    () -> {
        synchronized (lock) {
            System.out.println("thread3 got lock");
            while (state.get() < 2) {
                try {
                    System.out.println("thread3 waiting");
                    lock.wait();
                    System.out.println("thread3 wakeup");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println("thread3 finished");
            state.addAndGet(1);
        }
    }
);

thread3.start();
thread2.start();
thread1.start();

4 使用线程池

使用单线程的线程池

ExecutorService executorService = Executors.newSingleThreadExecutor();
executorService.submit(() -> {
    System.out.println("thread1 finished");
});
executorService.submit(() -> {
    System.out.println("thread2 finished");
});
executorService.submit(() -> {
    System.out.println("thread3 finished");
});
executorService.shutdown();

5 使用AQS的Condition(条件变量)

一个锁,两个条件;thread2等待condition1、thread3等待condition2

ReentrantLock lock = new ReentrantLock();
Condition condition1 = lock.newCondition();
Condition condition2 = lock.newCondition();
ReentrantLock reentrantLock = new ReentrantLock();
Condition c1 = reentrantLock.newCondition();
Condition c2 = reentrantLock.newCondition();

Thread thread1 = new Thread(() -> {
    try {
        Thread.sleep(1000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    reentrantLock.lock();
    System.out.println("thread1 got lock");
    System.out.println("thread1 finished");
    c1.signal();
    reentrantLock.unlock();
});

Thread thread2 = new Thread(() -> {
    reentrantLock.lock();
    System.out.println("thread2 got lock");
    try {
        c1.await();
        System.out.println("thread2 wakeup");
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    System.out.println("thread2 finished");
    c2.signal();
    reentrantLock.unlock();
});

Thread thread3 = new Thread(() -> {
    reentrantLock.lock();
    System.out.println("thread3 got lock");
    try {
        c2.await();
        System.out.println("thread3 wakeup");
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    System.out.println("thread3 finished");
    reentrantLock.unlock();
});

thread3.start();
thread2.start();
thread1.start();

6 使用CountDownLatch

两个Latch,thread2等待latch2、thread3等待latch3

CountDownLatch latch2 = new CountDownLatch(1);
CountDownLatch latch3 = new CountDownLatch(1);

Thread thread1 = new Thread(
    () -> {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("thread1 finished");
        latch2.countDown();
    }
);

Thread thread2 = new Thread(
    () -> {
        try {
            Thread.sleep(1000);
            latch2.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("thread2 finished");
        latch3.countDown();
    }
);

Thread thread3 = new Thread(
    () -> {
        try {
            latch3.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("thread3 finished");
    }
);

thread3.start();
thread2.start();
thread1.start();

7 使用CyclicBarrier(回环栅栏)

通过它可以实现让一组线程等待至某个状态之后再全部同时执行。叫做回环是因为当所有等待线程都被释放以后,CyclicBarrier可以被重用。暂且把这个状态就叫做barrier,当调用await()方法之后,线程就处于barrier了。

CyclicBarrier cyclicBarrier2 = new CyclicBarrier(2, () -> {System.out.println("thread1 and thread2 reached same await status");});
CyclicBarrier cyclicBarrier3 = new CyclicBarrier(2, () -> {System.out.println("thread2 and thread3 reached same await status");});

Thread thread1 = new Thread(
    () -> {
        try {
            System.out.println("thread1 finished");
            cyclicBarrier2.await();
        } catch (InterruptedException | BrokenBarrierException e) {
            e.printStackTrace();
        }
    }
);

Thread thread2 = new Thread(
    () -> {
        try {
            cyclicBarrier2.await();
            System.out.println("thread2 finished");
            cyclicBarrier3.await();
        } catch (InterruptedException | BrokenBarrierException e) {
            e.printStackTrace();
        }
    }
);

Thread thread3 = new Thread(
    () -> {
        try {
            cyclicBarrier3.await();
            System.out.println("thread3 finished");
        } catch (InterruptedException | BrokenBarrierException e) {
            e.printStackTrace();
        }
    }
);

thread3.start();
thread2.start();
thread1.start();

8 使用Semaphore(信号量)

Semaphore是一个计数信号量,从概念上将,Semaphore包含一组许可证,如果有需要的话,每个acquire()方法都会阻塞,直到获取一个可用的许可证,每个release()方法都会释放持有许可证的线程,并且归还Semaphore一个可用的许可证。然而,实际上并没有真实的许可证对象供线程使用,Semaphore只是对可用的数量进行管理维护。

前序线程执行之后,向信号量release一个许可证,后序线程通过acquire获取许可证,没有获取到则阻塞,获取到则执行

Semaphore semaphore2 = new Semaphore(0);
Semaphore semaphore3 = new Semaphore(0);

Thread thread1 = new Thread(
    () -> {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("thread1 finished");
        semaphore2.release();
    }
);

Thread thread2 = new Thread(
    () -> {
        try {
            Thread.sleep(1000);
            semaphore2.acquire();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("thread2 finished");
        semaphore3.release();
    }
);

Thread thread3 = new Thread(
    () -> {
        try {
            semaphore3.acquire();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("thread3 finished");
    }
);

thread3.start();
thread2.start();
thread1.start();

9 使用CompletableFuture

CompletableFuture completableFuture = new CompletableFuture();
completableFuture.runAsync(() -> {System.out.println("thread1 finished");})
        .thenRunAsync(() -> {System.out.println("thread2 finished");})
        .thenRunAsync(() -> {System.out.println("thread3 finished");});
  • 8
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值