有T1、T2、T3三个线程,怎么让三个线程顺序执行?T1执行结束T2执行,T2执行结束T3执行。
- join()方法
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(()->{
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("T1 执行完成...");
});
Thread t2 = new Thread(()->{
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("T2 执行完成...");
});
Thread t3 = new Thread(()->{
System.out.println("T3 执行完成...");
});
//使用 Thread.join() 等待线程执行完毕, 这种方式不优雅
t1.start();
t1.join();
t2.start();
t2.join();
t3.start();
t3.join();
}
- wait()方法
不推荐,不灵活
wait()的线程必须要先执行,否则其他线程notify()是无法唤醒的。Object.wait()/notify()的这种方式,锁的使用方式一定是先wait()再notify()的。
public static void main(String[] args) throws Exception{
Thread2 t2 = new Thread2();
Thread1 t1 = new Thread1(t2);
// Thread t3 = new Thread(t2);
// 期望顺序 t1->t2->t3
ExecutorService executorService = Executors.newFixedThreadPool(10);
// 这里必须要让t2先执行才能正常执行,否则会一直处于wait()
// 如果t1先拿到对象锁执行notify()无法唤醒t2,因为t2还没有拿到对象锁,未执行wait()
// 因此同一个锁的执行顺序:wait()->notify()
executorService.execute(t2);
Thread.sleep(100);
executorService.execute(t1);
executorService.shutdown();
while (!executorService.isTerminated()){
// 等待所有线程执行结束
}
System.exit(0);
}
class Thread2 implements Runnable{
@SneakyThrows
@Override
public void run() {
synchronized (this){
System.out.println("t2线程等待t1线程执行。。。");
this.wait();
System.out.println("t2线程等待t1线程执行。。。执行结束");
System.out.println("t2线程执行");
}
}
}
class Thread1 implements Runnable{
private final Object obj;
public Thread1(Object obj) {
this.obj = obj;
}
@Override
public void run() {
synchronized (obj){
// notify()不会立马释放对象锁,释放情景: 1.synchronized代码块执行完成; 2.主动释放 wait();
obj.notify();
System.out.println("t1线程开始执行");
System.out.println("t1线程执行结束");
}
}
}
- 使用重入锁Condition.await()方法
public class MyThread {
static ExecutorService executorService = Executors.newFixedThreadPool(3);
public static void main(String[] args) throws InterruptedException {
MyLock myLock = new MyLock();
Runnable t1 = myLock::thread1;
Runnable t2 = myLock::thread2;
Runnable t3 = myLock::thread3;
executorService.submit(t1);
executorService.submit(t2);
executorService.submit(t3);
Thread.sleep(1000);
myLock.getLock().lock();
// 唤醒线程t1
myLock.getCondition1().signal();
myLock.getLock().unlock();
executorService.shutdown();
}
@Data
static class MyLock{
private ReentrantLock lock = new ReentrantLock();
private Condition condition1 = lock.newCondition();
private Condition condition2 = lock.newCondition();
private Condition condition3 = lock.newCondition();
public void thread1(){
lock.lock();
try {
System.out.println("线程t1等待执行。。。。");
condition1.await();// await()执行的前提是线程获取了对象的控制权,否则会报错:java.lang.IllegalMonitorStateException
System.out.println("线程t1执行。。。。");
condition2.signal(); // 唤醒线程
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
lock.unlock();
}
}
public void thread2(){
lock.lock();
try {
System.out.println("线程t2等待执行。。。。");
condition2.await();// await()执行的前提是线程获取了对象的控制权,否则会报错:java.lang.IllegalMonitorStateException
System.out.println("线程t2执行。。。。");
condition3.signal();// 唤醒线程
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
lock.unlock();
}
}
public void thread3(){
lock.lock();
try {
System.out.println("线程t3等待执行。。。。");
condition3.await();// await()执行的前提是线程获取了对象的控制权,否则会报错:java.lang.IllegalMonitorStateException
System.out.println("线程t3执行。。。。");
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
lock.unlock();
}
}
}
}
- 建立单线程池:Executors.newSingleThreadExector()
串行执行任务
public class MyThread {
static ExecutorService executorService = Executors.newSingleThreadExecutor();
public static void main(String[] args) {
Thread thread1 = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("t1线程执行.....");
}
});
Thread thread2 = new Thread(new Runnable() {
@SneakyThrows
@Override
public void run() {
System.out.println("t2线程执行.....");
}
});
Thread thread3 = new Thread(new Runnable() {
@SneakyThrows
@Override
public void run() {
System.out.println("t3线程执行.....");
}
});
executorService.submit(thread1);
executorService.submit(thread2);
executorService.submit(thread3);
executorService.shutdown();//关闭线程池
}
}
- 计数器CountDownLatch
检测到CountDownLatch计数器为0时就可以继续向下执行 不用管thread是否执行完毕。
countDown()每调用一次 计数器减一
await()计数器减到0时候唤醒当前线程继续执行
package com.xuelangyun.web.controller;
import lombok.SneakyThrows;
import java.util.concurrent.CountDownLatch;
/**
* @author muxi.fs
* @date 2022/11/16 16:08
*/
public class MyThread {
private static CountDownLatch countDownLatch1 = new CountDownLatch(1);
private static CountDownLatch countDownLatch2 = new CountDownLatch(1);
public static void main(String[] args) {
Thread thread1 = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("t1线程执行.....");
countDownLatch1.countDown();
}
});
Thread thread2 = new Thread(new Runnable() {
@SneakyThrows
@Override
public void run() {
countDownLatch1.await();
System.out.println("t2线程执行.....");
countDownLatch2.countDown();
}
});
Thread thread3 = new Thread(new Runnable() {
@SneakyThrows
@Override
public void run() {
countDownLatch2.await();
System.out.println("t3线程执行.....");
countDownLatch1.countDown();
}
});
thread3.start();
thread2.start();
thread1.start();
}
}
- Senaphore信号量
和CountDownLatch一样,作为信号来传递
public class MyThread {
static ExecutorService executorService = Executors.newFixedThreadPool(10);
static Semaphore semaphore1 = new Semaphore(0);
static Semaphore semaphore2 = new Semaphore(0);
public static void main(String[] args) throws InterruptedException {
Thread thread1 = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("线程t1执行.....");
semaphore1.release(); // 信号量1 +1
}
});
Thread thread2 = new Thread(new Runnable() {
@SneakyThrows
@Override
public void run() {
semaphore1.acquire(); // 信号量-1 总数为0时候会等待
System.out.println("线程t2执行.....");
semaphore2.release();
}
});
Thread thread3 = new Thread(new Runnable() {
@SneakyThrows
@Override
public void run() {
semaphore2.acquire(); // 信号量-1 总数为0时候会等待
System.out.println("线程t3执行.....");
}
});
executorService.submit(thread1); // 信号量1先-1
executorService.submit(thread2);
executorService.submit(thread3);
executorService.shutdown();
}
}
- FutureTask
通过FutureTask阻塞的特性顺序执行,类似于单线程池执行
public class MyThread {
public static void main(String[] args) throws ExecutionException, InterruptedException {
ExecutorService executorService = Executors.newFixedThreadPool(3);
//Future> submit(Runnable task);
Object t1 = executorService.submit(new Runnable() {
@Override
public void run() {
System.out.println("线程t1执行。。。。");
}
}).get();
Object t2 = executorService.submit(new Runnable() {
@Override
public void run() {
System.out.println("线程t2执行。。。。");
}
}).get();
Object t3 = executorService.submit(new Runnable() {
@Override
public void run() {
System.out.println("线程t3执行。。。。");
}
}).get();
executorService.shutdown();
}
}
executorService.submit()底层使用FutureTask实现
- CompletableFuture(推荐)
public class MyThread {
/**
* CompletableFuture
* 提供函数式编程的能力,可帮助我们完成复杂的线程的阶段行编程(CompletionStage)
* @param args
*/
public static void main(String[] args) {
ExecutorService executorService = Executors.newFixedThreadPool(3);
Runnable t1 = () -> System.out.println("线程t1执行...");
Runnable t2 = () -> System.out.println("线程t2执行...");
Runnable t3 = () -> System.out.println("线程t3执行...");
// 异步执行
CompletableFuture.runAsync(t1,executorService).thenRun(t2).thenRun(t3);
// 停止接受新任务,当已有任务将执行完,关闭线程池
executorService.shutdown();
}
}