众所周知,线程是一种比较昂贵的资源,其主要的开销有以下几个方面
因此,对于线程这种代价比较昂贵的资源,需要使用一种合理的方式去使用,而线程池就是一种能够有效利用线程的方式。
以java.util.concurrent.ThreadPoolExecutor类为例,其参数最多构造函数如下
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
RejectedExecutionHandler handler) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
Executors.defaultThreadFactory(), handler);
}
各参数含义
创建线程池
public class ThreadPoolDemo {
public static void main(String[] args) {
ArrayBlockingQueue<Runnable> workQueue = new ArrayBlockingQueue<>(10);
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(5, 10, 10, TimeUnit.SECONDS, workQueue);
for (int i = 0; i < 100; i++) {
Task task = new Task();
threadPoolExecutor.submit(task);
System.out.println("poolSize:" + threadPoolExecutor.getPoolSize());
System.out.println("workQueue:" + threadPoolExecutor.getQueue().size());
System.out.println("largestPoolSize:" + threadPoolExecutor.getLargestPoolSize());
System.out.println("activeCount:" + threadPoolExecutor.getActiveCount());
System.out.println("taskCount:" + threadPoolExecutor.getTaskCount());
System.out.println("completedTaskCount:" + threadPoolExecutor.getCompletedTaskCount());
System.out.println("------------------------------------------");
}
ExecutorService executorService = Executors.newFixedThreadPool(1);
}
static class Task implements Runnable {
@Override
public void run() {
try {
Thread.sleep(1000000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("ThreadName:" + Thread.currentThread().getName());
}
}
}
运行结果
poolSize:1
workQueue:0
largestPoolSize:1
activeCount:1
taskCount:1
completedTaskCount:0
------------------------------------------
...
poolSize:5
workQueue:0
largestPoolSize:5
activeCount:5
taskCount:5
completedTaskCount:0
------------------------------------------
可以看出在submit前5个任务的时候,线程池为每个任务都创建了一个线程,poolSize为5达到了核心线程数,继续submit任务
poolSize:5
workQueue:1
largestPoolSize:5
activeCount:5
taskCount:6
completedTaskCount:0
------------------------------------------
...
poolSize:5
workQueue:10
largestPoolSize:5
activeCount:5
taskCount:15
completedTaskCount:0
------------------------------------------
在达到核心线程数5后可以发现继续submit任务后线程池并不会再继续创建线程了,任务都会被放到工作队列之中,直到达到工作队列的容量上限,继续submit任务
poolSize:6
workQueue:10
largestPoolSize:6
activeCount:6
taskCount:16
completedTaskCount:0
------------------------------------------
...
poolSize:10
workQueue:10
largestPoolSize:10
activeCount:10
taskCount:20
completedTaskCount:0
------------------------------------------
当达到workQueue的上限10后,继续submit任务可以发现线程池又继续增加线程直到达到最大线程数,如果再继续添加任务那么线程线程池就会拒绝任务并调用默认的RejectedExecutionHandler向外抛出异常
Exception in thread "main" java.util.concurrent.RejectedExecutionException: Task java.util.concurrent.FutureTask@1453f44 rejected from java.util.concurrent.ThreadPoolExecutor@ad8086[Running, pool size = 10, active threads = 10, queued tasks = 10, completed tasks = 0]
at java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:2063)
at java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:830)
at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1379)
at java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:112)
at thread.ch8.ThreadPoolDemo.main(ThreadPoolDemo.java:20)
通过这个demo就可以比较快速的了解线程池的构成与运作方式了,至于更加深入的内容在之后的博客中会继续分析。
原文:https://www.cnblogs.com/cy1995/p/13280218.html