多线程中的Join() CountDownLatch CyclicBarrier Semaphore
一个生动的例子
CountDownLatch
: 一个老师上课,要等所有学生都来了才开始 , 即单线程
CyclicBarrier
:一个项目开工,需要所有部门的员工都来了才能开始工作, 多线程,功能更强大
Semaphore
:限流器, 管道就这么大,走了多少,才能再进多少。 类似检票站,或者高速ETC
https://mp.weixin.qq.com/s/tkLXP7NSYJaihJZW9jzGpw 万字多线程总结
Join: Thread自带方法
主线程main中两个线程 A和B, A.join(); B.join() 即等待所有的线程执行完毕,主线程才继续往下走
public static void main(String[] args) throws InterruptedException{
Thread parse1 = new Thread(new Runnable() {
@Override
public void run() {
}
});
Thread parse2 = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("parse2 finish");
}
});
parse1.start();
parse2.start();
parse1.join();
parse2.join(); //这两个都执行完,才会往下走
System.out.println("all parse finish");
}
CountDownLatch
上面的join是一个简单的CountDownLatch
, 下面看看 CountDownLatch用法
public class CountDownLatchTest {
private static CountDownLatch c = new CountDownLatch(2); //构造方法中传入int,如果想等n个点完成,就传n, 类似于打点,之后打n个点
public static void main(String[] args) throws InterruptedException{
new Thread(new Runnable() {
@Override
public void run() {
System.out.println(1);
c.countDown(); //第一个点, 执行后 n-1
System.out.println(2);
c.countDown(); //第二个点
}
}).start();
c.await(); //阻塞主线程,直到n =0
System.out.println(3);
}
}
Semaphore:控制并发线程数
控制流量
public class SemaphoreTest {
private static final int THREAD_COUNT = 30;
private static Semaphore s = new Semaphore(10);
private static ExecutorService e = Executors.newFixedThreadPool(THREAD_COUNT);
public static void main(String[] args) {
for (int i = 0; i < THREAD_COUNT; i++) {
e.execute(new Runnable() {
@Override
public void run() {
try {
s.acquire();
System.out.println("save data");
s.release();
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
});
}
e.shutdown();
}
}
代码中有30个线程,每次允许执行10个并发执行。
Semaphore(int num)构造方法表示允许的许可证数量。 上面demo是最大允许10个。 使用方法:
- 使用semaphore.acquire() 获取一个许可证
- 使用完用 release() 释放
线程池
4个核心参数
4种队列
4种默认拒绝策略
向队列提交任务:execute() 和 submit
- execute 提交不需要返回值的任务
- submit提交的是一个有返回值的任务,使用
Executor框架
应用程序通过Executor框架进行上层线程的调度,然后交由操作系统内核进行Cpu线程调度
3大组成部分
- 任务:实现Runnable和Callable接口的执行任务
- 任务的执行:核心接口 Executor,和继承自Executor的 ExecutorService 接口。 其中有两个关键类
ThreadPoolExecutor
和ScheduledThreadPoolExecutor
- 异步计算的结果: 包括接口Future和实现Future的 FutureTask