线程池是指在初始化一个多线程应用程序过程中创建一个线程集合,然后在需要执行新的任务时重用这些线程而不是新建一个线程。线程池中线程的数量通常完全取决于可用内存数量和应用程序的需求。然而,增加可用线程数量是可能的。线程池中的每个线程都有被分配一个任务,一旦任务已经完成了,线程回到池子中并等待下一次分配任务。 java.util.concurrent.Executors提供了一个 java.util.concurrent.Executor接口的实现用于创建线程池,一个线程池包括以下四个基本组成部分: 1、线程池管理器(ThreadPool):用于创建并管理线程池,包括 创建线程池,销毁线程池,添加新任务; |
---|
1、重用存在的线程,减少对象创建、消亡的系统开销,过于频繁的创建/销毁线程,会很大程度上影响处理效率
2、可有效控制最大并发线程数,提高系统资源的使用率,同时避免过多资源竞争,避免堵塞
3、对线程进行一些简单的管理
|
---|
|
---|
//五个参数的构造函数
public ThreadPoolExecutor(
int
corePoolSize,
int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue
)
//六个参数的构造函数-1 public ThreadPoolExecutor(
int
corePoolSize,
int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory
)
//六个参数的构造函数-2 public ThreadPoolExecutor(
int
corePoolSize,
int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, RejectedExecutionHandler handler
)
//七个参数的构造函数 public ThreadPoolExecutor(
int
corePoolSize,
int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler
)
| int corePoolSize => 该线程池中核心线程数最大值 int maximumPoolSize => 该线程池中线程总数最大值 long keepAliveTime => 线程池中非核心线程闲置超时时长 TimeUnit unit => 参数的时间单位,枚举类型
|
---|
1、当线程池小于corePoolSize时,新提交任务将创建一个新线程执行任务,即使此时线程池中存在空闲线程。 2、当线程池达到corePoolSize时,新提交任务将被放入workQueue中,等待线程池中任务调度执行 3、当workQueue已满,且maximumPoolSize>corePoolSize时,新提交任务会创建新线程执行任务 4、当提交任务数超过maximumPoolSize时,新提交任务由RejectedExecutionHandler处理 5、当线程池中超过corePoolSize线程,空闲时间达到keepAliveTime时,关闭空闲线程 6、当设置allowCoreThreadTimeOut(true)时,线程池中corePoolSize线程空闲时间达到keepAliveTime也将关闭 |
---|
1、newSingleThreadExecutor
public static ExecutorService newSingleThreadExecutor() { return new FinalizableDelegatedExecutorService (new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>())); }
return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>()); }
3、newCachedThreadPool ( newFixedThreadPool (int nThreads))
public static ExecutorService newCachedThreadPool() { return new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>()); }
4、 ScheduledThreadPoolExecutor ( newScheduledThreadPool(int corePoolSize) )
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
return new ScheduledThreadPoolExecutor(corePoolSize); }
public ScheduledThreadPoolExecutor(int corePoolSize) { super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS, new DelayedWorkQueue()); }
|
---|
ExecutorService的方法
|
---|
示例
执行Runnable任务
public class Test {
public static void main(String[] args) {
ExecutorService service = Executors.newCachedThreadPool();
// ExecutorService service = Executors.newFixedThreadPool(5);
// ExecutorService service = Executors.newSingleThreadExecutor();
for(int i = 0; i < 20; i ++) {
service.execute(new MyThread(i));
}
service.shutdown();
}
}
public class MyThread implements Runnable {
public int index;
public MyThread (int index) {
this.index = index;
}
@Override
public void run() {
System.out.println(TimeUtils.getDateStr() + " Thread-" + Thread.currentThread().getName() + " " + index);
try {
Thread.sleep(MathConstant.INT_1000);
} catch (Exception e) {
e.printStackTrace();
}
}
}
执行Callable任务
public class Test {
ExecutorService executorService = Executors.newCachedThreadPool();
List<Future<String>> resultList = new ArrayList<Future<String>>();
//创建10个任务并执行
for (int i = 0; i < 10; i++){
//使用ExecutorService执行Callable类型的任务,并将结果保存在future变量中
Future<String> future = executorService.submit(new MyThread2(i));
//将任务执行结果存储到List中
resultList.add(future);
}
//遍历任务的结果
for (Future<String> fs : resultList){
try{
while(!fs.isDone());//Future返回如果没有完成,则一直循环等待,直到Future返回完成
System.out.println(fs.get()); //打印各个线程(任务)执行的结果
}catch(InterruptedException e){
e.printStackTrace();
}catch(ExecutionException e){
e.printStackTrace();
}finally{
//启动一次顺序关闭,执行以前提交的任务,但不接受新任务
executorService.shutdown();
}
}
}
public class MyThread2 implements Callable<String> {
public int index;
public MyThread2(int index) {
this.index = index;
}
@Override
public String call() throws Exception {
String name = Thread.currentThread().getName();
System.out.println(TimeUtils.getDateStr() + " Thread-" + name + " " + index);
return name;
}
}