sleep()方法
即通过 Thread.sleep() 方法,来等待子线程执行完毕。这种方式明显有bug,因为不确定子线程执行耗时。
join()方法
即通过 thread.join() 方法,来等待子线程执行完毕。且该方法会把指定的线程加入到当前线程,可以将多个交替执行的线程合并为顺序执行的线程。
package com.example.demo;
import lombok.extern.slf4j.Slf4j;
import java.util.concurrent.TimeUnit;
@Slf4j
public class ThreadTest {
public static void main(String[] args) throws InterruptedException {
log.info("开始执行主线程...");
for (int i = 0; i < 10; i++) {
Thread thread = new Thread(() -> {
log.info("开始执行子线程...等待1秒钟");
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
});
thread.start();
thread.join();
}
log.info("恢复执行主线程...");
}
}
/**
* 以上代码执行结果
* 20:21:54.073 [main] INFO com.example.demo.ThreadTest - 开始执行主线程...
* 20:21:54.219 [Thread-0] INFO com.example.demo.ThreadTest - 开始执行子线程...等待1秒钟
* 20:21:55.222 [Thread-1] INFO com.example.demo.ThreadTest - 开始执行子线程...等待1秒钟
* 20:21:56.223 [Thread-2] INFO com.example.demo.ThreadTest - 开始执行子线程...等待1秒钟
* 20:21:57.225 [Thread-3] INFO com.example.demo.ThreadTest - 开始执行子线程...等待1秒钟
* 20:21:58.227 [Thread-4] INFO com.example.demo.ThreadTest - 开始执行子线程...等待1秒钟
* 20:21:59.229 [Thread-5] INFO com.example.demo.ThreadTest - 开始执行子线程...等待1秒钟
* 20:22:00.232 [Thread-6] INFO com.example.demo.ThreadTest - 开始执行子线程...等待1秒钟
* 20:22:01.235 [Thread-7] INFO com.example.demo.ThreadTest - 开始执行子线程...等待1秒钟
* 20:22:02.239 [Thread-8] INFO com.example.demo.ThreadTest - 开始执行子线程...等待1秒钟
* 20:22:03.242 [Thread-9] INFO com.example.demo.ThreadTest - 开始执行子线程...等待1秒钟
* 20:22:04.242 [main] INFO com.example.demo.ThreadTest - 恢复执行主线程...
*/
CountDownLatch
CountDownLatch能够使一个线程在等待另外一些线程完成各自工作之后,再继续执行。内部使用一个计数器实现。计数器初始值为线程的数量。当每一个线程完成自己任务后,触发countDownLatch.countDown()方法,使计数器的值减一。当计数器的值为0时,表示线程都已经完成任务,然后在CountDownLatch上等待的线程就可以恢复执行接下来的任务。
package com.example.demo;
import lombok.extern.slf4j.Slf4j;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
@Slf4j
public class ThreadTest {
public static void main(String[] args) throws InterruptedException {
log.info("开始执行主线程...");
CountDownLatch countDownLatch = new CountDownLatch(10);
for (int i = 0; i < 10; i++) {
Thread thread = new Thread(() -> {
log.info("开始执行子线程...等待1秒钟");
try {
TimeUnit.SECONDS.sleep(1);
countDownLatch.countDown();
} catch (InterruptedException e) {
e.printStackTrace();
}
});
thread.start();
}
countDownLatch.await();
log.info("恢复执行主线程...");
}
}
/**
* 以上代码执行结果
* 20:27:25.516 [main] INFO com.example.demo.ThreadTest - 开始执行主线程...
* 20:27:25.647 [Thread-0] INFO com.example.demo.ThreadTest - 开始执行子线程...等待1秒钟
* 20:27:25.647 [Thread-1] INFO com.example.demo.ThreadTest - 开始执行子线程...等待1秒钟
* 20:27:25.648 [Thread-3] INFO com.example.demo.ThreadTest - 开始执行子线程...等待1秒钟
* 20:27:25.649 [Thread-4] INFO com.example.demo.ThreadTest - 开始执行子线程...等待1秒钟
* 20:27:25.649 [Thread-5] INFO com.example.demo.ThreadTest - 开始执行子线程...等待1秒钟
* 20:27:25.649 [Thread-6] INFO com.example.demo.ThreadTest - 开始执行子线程...等待1秒钟
* 20:27:25.650 [Thread-8] INFO com.example.demo.ThreadTest - 开始执行子线程...等待1秒钟
* 20:27:25.650 [Thread-7] INFO com.example.demo.ThreadTest - 开始执行子线程...等待1秒钟
* 20:27:25.651 [Thread-9] INFO com.example.demo.ThreadTest - 开始执行子线程...等待1秒钟
* 20:27:25.655 [Thread-2] INFO com.example.demo.ThreadTest - 开始执行子线程...等待1秒钟
* 20:27:26.657 [main] INFO com.example.demo.ThreadTest - 恢复执行主线程...
*/
CyclicBarrier
与 CountDownLatch 类颇为相似。CyclicBarrier字面意思是“可重复使用的栅栏”。CyclicBarrier 的源码实现和 CountDownLatch 大相径庭,CountDownLatch 基于 AQS 的共享模式的使用,而 CyclicBarrier 基于 Condition 来实现的。在CyclicBarrier类的内部同样有一个计数器,每个线程在到达屏障点的时候都会调用await方法将自己阻塞,此时计数器会减一,当计数器的值为0时,所有因调用await方法而被阻塞的线程将被唤醒。
package com.example.demo;
import lombok.extern.slf4j.Slf4j;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.TimeUnit;
@Slf4j
public class ThreadTest {
public static void main(String[] args) throws InterruptedException {
log.info("开始执行主线程...");
CyclicBarrier cyclicBarrier = new CyclicBarrier(10);
for (int i = 0; i < 9; i++) {
Thread thread = new Thread(() -> {
try {
log.info("开始执行子线程...等待1秒钟");
TimeUnit.SECONDS.sleep(1);
cyclicBarrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
});
thread.start();
}
try {
cyclicBarrier.await();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
log.info("恢复执行主线程...");
}
}
/**
* 以上代码执行结果
* 20:50:33.296 [main] INFO com.example.demo.ThreadTest - 开始执行主线程...
* 20:50:33.427 [Thread-2] INFO com.example.demo.ThreadTest - 开始执行子线程...等待1秒钟
* 20:50:33.427 [Thread-1] INFO com.example.demo.ThreadTest - 开始执行子线程...等待1秒钟
* 20:50:33.428 [Thread-0] INFO com.example.demo.ThreadTest - 开始执行子线程...等待1秒钟
* 20:50:33.429 [Thread-6] INFO com.example.demo.ThreadTest - 开始执行子线程...等待1秒钟
* 20:50:33.430 [Thread-5] INFO com.example.demo.ThreadTest - 开始执行子线程...等待1秒钟
* 20:50:33.429 [Thread-3] INFO com.example.demo.ThreadTest - 开始执行子线程...等待1秒钟
* 20:50:33.430 [Thread-7] INFO com.example.demo.ThreadTest - 开始执行子线程...等待1秒钟
* 20:50:33.431 [Thread-8] INFO com.example.demo.ThreadTest - 开始执行子线程...等待1秒钟
* 20:50:33.434 [Thread-4] INFO com.example.demo.ThreadTest - 开始执行子线程...等待1秒钟
* 20:50:34.440 [main] INFO com.example.demo.ThreadTest - 恢复执行主线程...
*/
线程池技术
package com.example.demo;
import lombok.extern.slf4j.Slf4j;
import java.util.concurrent.*;
@Slf4j
public class ThreadTest {
public static void main(String[] args) {
ExecutorService service = Executors.newFixedThreadPool(10);
log.info("开始执行主线程...");
for (int i = 0; i < 10; i++) {
service.submit(() -> log.info("开始执行子线程..."));
}
try {
service.shutdown();
if (service.awaitTermination(Integer.MAX_VALUE, TimeUnit.SECONDS)) {
log.info("恢复执行主线程...");
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
/**
* 以上代码执行结果
* 20:55:30.433 [main] INFO com.example.demo.ThreadTest - 开始执行主线程...
* 20:55:30.605 [pool-1-thread-2] INFO com.example.demo.ThreadTest - 开始执行子线程...
* 20:55:30.605 [pool-1-thread-1] INFO com.example.demo.ThreadTest - 开始执行子线程...
* 20:55:30.606 [pool-1-thread-3] INFO com.example.demo.ThreadTest - 开始执行子线程...
* 20:55:30.608 [pool-1-thread-6] INFO com.example.demo.ThreadTest - 开始执行子线程...
* 20:55:30.608 [pool-1-thread-5] INFO com.example.demo.ThreadTest - 开始执行子线程...
* 20:55:30.608 [pool-1-thread-4] INFO com.example.demo.ThreadTest - 开始执行子线程...
* 20:55:30.609 [pool-1-thread-7] INFO com.example.demo.ThreadTest - 开始执行子线程...
* 20:55:30.609 [pool-1-thread-8] INFO com.example.demo.ThreadTest - 开始执行子线程...
* 20:55:30.610 [pool-1-thread-9] INFO com.example.demo.ThreadTest - 开始执行子线程...
* 20:55:30.611 [pool-1-thread-10] INFO com.example.demo.ThreadTest - 开始执行子线程...
* 20:55:30.611 [main] INFO com.example.demo.ThreadTest - 恢复执行主线程...
*/
本文由 Administrator 创作,采用 知识共享署名4.0 国际许可协议进行许可
本站部分文章采集自互联网,因某些原因未注明出处,如有侵权,请留言告知。