1.线程池与线程性能对比
首先用线程的方法进行循环进行输出
public static void main(String[] args) throws InterruptedException {
Long start = System.currentTimeMillis();
Random random = new Random();
List<Integer> list = new ArrayList<>();
for (int i = 0; i < 100000; i++) {
Thread thread = new Thread() {
@Override
public void run() {
list.add(random.nextInt());
}
};
thread.start();
thread.join();
}
System.out.println("时间" + (System.currentTimeMillis() - start));
System.out.println("大小" + list.size());
}
输出结果为
时间18830
大小100000
使用线程池的方法进行循环输出
public static void main(String[] args) throws InterruptedException {
Long start = System.currentTimeMillis();
Random random = new Random();
List<Integer> list = new ArrayList<>();
ExecutorService executorService = Executors.newSingleThreadExecutor();
for (int i = 0; i < 100000; i++) {
executorService.execute(new Runnable() {
@Override
public void run() {
list.add(random.nextInt());
}
});
}
executorService.shutdown();
executorService.awaitTermination(1, TimeUnit.DAYS);
System.out.println("时间" + (System.currentTimeMillis() - start));
System.out.println("大小" + list.size());
}
输出结果为
时间69
大小100000
那么为什么相差这么大呢?
使用Thread创建线程:
十万次循环,每循环一次创建一个Thread,创建Thread的时候我们的线程是需要CPU进行分配时间调度的.
线程之间需要进行切换,那么切换也是占用资源的,这就是影响效率变慢的原因.
使用线程池:
进行十万次循环每循环一次也创建Runnable,那为什么就这么快呢,带着这个疑问接着往下看(不是线程复用的原因)
2.new ThreadPoolExecutor详解
下面三个哪个最先执行完成呢?
public static void main(String[] args) {
ExecutorService executorService1 = Executors.newCachedThreadPool(); //快
ExecutorService executorService2 = Executors.newFixedThreadPool(10); //慢
ExecutorService executorService3 = Executors.newSingleThreadExecutor(); //最慢
for (int i = 1; i <= 100; i++) {
executorService2.execute(new MyTask(i));
}
}
static class MyTask implements Runnable {
int i = 0;
public MyTask(int i) {
this.i = i;
}
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + "---" + i);
try {
Thread.sleep(1000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
上面三个都是用的同一个方法如下
new ThreadPoolExecutor
那么为什么速度相差这么多的原因呢?
因为底层传递的参数不一样,也就是因为传递的线程数量不一样导致我们执行的任务快慢有区别
底层调用方法如下
线程池默认会创建一些线程,而创建线程和销毁线程是非常占用资源的,所以线程池就会事先创建一些线程,而创建具体多少个线程取决于第一个参数corePoolSize
maximumPoolSize参数就是比如双11传递50个核心线程是不够的,需要500,所以第二个参数就传递450就是非核心线程,
非核心线程是有结束时间的unit设置时间单位,keepAliveTime设置时长
workQueue比如有5000个订单同时执行,那么我们就会用队列进行排队
threadFactory非核心线程的450个就是重这个工厂里面来
handler拒绝策略比如有6000个订单,队列设置了5000那么还剩1000就会拒绝掉,后面1000订单就不处理了
public ThreadPoolExecutor(int corePoolSize, //核心线程数
int maximumPoolSize, //非核心线程数
long keepAliveTime, //时间
TimeUnit unit, //时间单位
BlockingQueue<Runnable> workQueue, //队列
ThreadFactory threadFactory, //线程工厂
RejectedExecutionHandler handler) //拒绝策略