前言
首先,肯定要先说说,为什么要用那个线程池?
其实无论在计算机领域里面还是在人类社会里面,为了达到某个操作,创建另一资源以及销毁是消耗很大的。
我好像又不说人话了……文字概念解释总是比较难懂的……
故事看懂了吧?本灵魂画师说的就是这个故事,没有公司会这么做,因为一个员工是一个很重要的资源,不好招的。就像一个线程不好创建的,所以最好是平时搞个池子(公司/线程池)把它们装起来,要用的时候随时能用。这就是线程池的作用啦~
线程池是个怎样的结构体系
结构清晰明了,解释一下接口、实现类
Executor: 负责线程使用和调度的总接口
|– ExecutorService 线程池主接口
|– AbstractExecutorService 线程池抽象类
|– ThreadPoolExecutor 线程池实现类
|– ScheduleExecutorService 可调度的线程池接口
|– SchedulThreadPoolExecutor 可调度的线程池实现类
怎么用?
package com.pochi.juc;
import java.util.concurrent.*;
public class ThreadPoolProblem {
public static void main(String[] args) throws ExecutionException, InterruptedException {
// Executors是一个工具类,提供四种线程池
ExecutorService executorService = Executors.newFixedThreadPool(5);
// 从线程池开出10条线程
for (int i = 0; i < 10; i++) {
// 这就相当于start了,除了可以传Callable也可以传Runnable
Future<Integer> submit = executorService.submit(new ExecutorDemo());
// 把结果打印出来吧
System.out.println(submit.get());
}
// 注意关掉池子
executorService.shutdown();
}
}
class ExecutorDemo implements Callable<Integer> {
int sum;
@Override
public Integer call() throws Exception {
// 其实就是从1加到100操作
for (int i = 0; i < 100; i++) {
sum += i + 1;
}
// 打印出线程名
System.out.print(Thread.currentThread().getName()+"::");
return sum;
}
}
结果
pool-1-thread-1::5050
pool-1-thread-2::5050
pool-1-thread-3::5050
pool-1-thread-4::5050
pool-1-thread-5::5050
pool-1-thread-1::5050
pool-1-thread-2::5050
pool-1-thread-3::5050
pool-1-thread-4::5050
pool-1-thread-5::5050
如果加上了时间调度的线程池是咋样的呢?
这里是加了时间调度的线程池
所谓的时间调度,就是可以做延迟呀之类的。看看代码吧~
package com.pochi.juc;
import java.time.LocalTime;
import java.util.concurrent.*;
public class ScheduleThreadPoolProblem {
public static void main(String[] args) throws ExecutionException, InterruptedException {
ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(5);
// 这里介绍三个方法
// schedule(Callable/Runnable,延迟(一般填具体数字),延迟的单位是一天/一分钟还是...)
ScheduledFuture<Integer> schedule = scheduledExecutorService.schedule(new Callable<Integer>() {
Integer sum=0;
@Override
public Integer call() throws Exception {
for (int i = 0; i < 100; i++) {
sum += i + 1;
}
return sum;
}
}, 1, TimeUnit.SECONDS);
System.out.println("schedule ::"+schedule.get());
// scheduleAtFixedRate(Runnable只能这个,初始化延迟,每次延迟间隔,延迟单位)
scheduledExecutorService.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("scheduleAtFixedRate::"+LocalTime.now());
}
}, 1, 2, TimeUnit.SECONDS);
//scheduleWithFixedDelay(Runnable只能这个,初始化延迟,每次延迟间隔,延迟单位)
scheduledExecutorService.scheduleWithFixedDelay(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("scheduleWithFixedDelay::"+LocalTime.now());
}
}, 1, 2, TimeUnit.SECONDS);
}
}
结果
schedule ::5050
scheduleWithFixedDelay::22:17:22.411
scheduleAtFixedRate::22:17:22.418
scheduleAtFixedRate::22:17:24.269
scheduleWithFixedDelay::22:17:25.414
scheduleAtFixedRate::22:17:26.269
scheduleAtFixedRate::22:17:28.269
scheduleWithFixedDelay::22:17:28.415
scheduleAtFixedRate::22:17:30.268
scheduleWithFixedDelay::22:17:31.417
scheduleAtFixedRate::22:17:32.269
(一直不停的话,会继续下去)
看出什么问题
scheduleWithFixedDelay 和 scheduleAtFixedRate 有什么区别?看起来,方法参数都是一样的,返回值也是一样的。
注意分析结果
scheduleWithFixedDelay::22:17:22.411
scheduleAtFixedRate::22:17:22.418
scheduleAtFixedRate::22:17:24.269
scheduleWithFixedDelay::22:17:25.414
看,其实,两者在里面都是有加入1s的sleep,但是两者的打印结果却是不同的,scheduleWithFixedDelay中,等那1s之后,才继续间隔2s,打印的。所以,两条输出之间的时间是3s间隔。而scheduleAtFixedRate两条打印之间的间隔是2s。
那么,那1s去哪儿了?
后记
这个线程池的解释还好吧?