java线程池
1. 为什么使用线程池
1、降低资源的消耗
2、提高响应的速度
3、方便管理。
线程池可以达到:线程复用、可以控制最大并发数、管理线程的目的
2. 线程池的使用
2.1 Executors的三种方法
package pool;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* study01
*
* @author : xgj
* @description : de
* @date : 2020-09-21 10:18
**/
public class ThreadPool {
public static void main(String[] args) {
//创建只有一个线程的线程池,但是其阻塞队列长度可以达到Integer.MAX_VALUE
ExecutorService threadPool = Executors.newSingleThreadExecutor();
for (int i = 0; i <10 ; i++) {
threadPool.execute(()->{
//输出线程名
System.out.println(Thread.currentThread().getName());
});
}
//使用完成后需要进行关闭
threadPool.shutdown();
}
}
运行截图
package pool;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* study01
*
* @author : xgj
* @description : de
* @date : 2020-09-21 10:18
**/
public class ThreadPool {
public static void main(String[] args) {
//创建指定个数的线程池,其阻塞队列长度可以达到Integer.MAX_VALUE
ExecutorService threadPool = Executors.newFixedThreadPool(5);
for (int i = 0; i <10 ; i++) {
threadPool.execute(()->{
//输出线程的名字
System.out.println(Thread.currentThread().getName());
});
}
//使用完成后需要进行关闭
threadPool.shutdown();
}
}
运行结果:
package pool;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* study01
*
* @author : xgj
* @description : de
* @date : 2020-09-21 10:18
**/
public class ThreadPool {
public static void main(String[] args) {
//创建个数动态添加的线程池,其数量可以达到Integer.MAX_VALUE
ExecutorService threadPool = Executors.newCachedThreadPool();
for (int i = 0; i <10 ; i++) {
threadPool.execute(()->{
//输出线程的名字
System.out.println(Thread.currentThread().getName());
});
}
//使用完成后需要进行关闭
threadPool.shutdown();
}
}
运行结果:
但是实际开发中最好不要通过Executors创建,而是自己通过ThreadPoolExecutor创建,这样可以自定义设定参数,策略。其实前面三种相当于默认提供的工具类:
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>()));
}
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}
本质还是通过ThreadPoolExecutor创建的线程池。
2.2 推荐使用ThreadPoolExecutor创建线程池
public ThreadPoolExecutor(int corePoolSize,//核心线程数 (默认会由这么多线程)
int maximumPoolSize,//最大核心线程数 (如果默认数量的线程不够,允许动态添加的线程数上限)
long keepAliveTime, //超出默认线程数的线程空闲这么长时间后销毁
TimeUnit unit,//超时单位
BlockingQueue<Runnable> workQueue,//阻塞队列
ThreadFactory threadFactory,//线程工厂 一般不会改变
RejectedExecutionHandler handler//拒绝策略 注意 不仅仅只是执行的线程,而是 最大线程数+阻塞队列的长度。
) {
if (corePoolSize < 0 ||
maximumPoolSize <= 0 ||
maximumPoolSize < corePoolSize ||
keepAliveTime < 0)
throw new IllegalArgumentException();
if (workQueue == null || threadFactory == null || handler == null)
throw new NullPointerException();
this.corePoolSize = corePoolSize;
this.maximumPoolSize = maximumPoolSize;
this.workQueue = workQueue;
this.keepAliveTime = unit.toNanos(keepAliveTime);
this.threadFactory = threadFactory;
this.handler = handler;
}
拒接策略:
new ThreadPoolExecutor.AbortPolicy() // 直接抛出异常
new ThreadPoolExecutor.DiscardPolicy() //队列满了,直接丢弃任务,不会抛出异常!
new ThreadPoolExecutor.DiscardOldestPolicy() //队列满了,尝试去和早的竞争,也不会抛出异常!
new ThreadPoolExecutor.CallerRunsPolicy() // 将任务交给原线程执行。