简介
一个线程的核心线程数是4, 最大线程数是8, 有一个任务提交过来, 迅速执行王弼, 如果再来一个任务, 那么线程池是新建一个线程去执行还是会复用之前的线程?
参考链接
https://blog.csdn.net/hu10131013/article/details/105665232 (逻辑图片清晰)
https://www.cnblogs.com/jxxblogs/p/11655670.html (测试代码来源)
answer
根据线程创建的逻辑而言.
如果没有创建了4个核心线程, 会创建一个新线程来执行. 虽然第一个线程使用完毕了.
测试代码
import com.sun.xml.internal.ws.util.StringUtils;
import java.io.Console;
import java.util.concurrent.*;
/**
* Created by lee on 2021/6/28.
*/
public class ThreadPoolLocal {
public static void main(String[] args) throws InterruptedException {
int size = 5;
ThreadPoolExecutor es1 = new ThreadPoolExecutor(
4, // corePoolSize
8, // int maximumPoolSize
1,// long keepAliveTime
TimeUnit.DAYS, // TimeUnit unit
new LinkedBlockingQueue<>(10) // BlockingQueue<Runnable> workQueue
);
for(int i=0; i<size; i++){
es1.execute(new DemoTask(i));
System.out.println("poolSize: " + es1.getPoolSize());
System.out.println("corePoolSize: " + es1.getCorePoolSize());
System.out.println("maximumPoolSize:" + es1.getMaximumPoolSize());
System.out.println("queue:" + es1.getQueue().size());
System.out.println("completedTaskCount:" + es1.getCompletedTaskCount());
System.out.println("largestPoolSize:" + es1.getLargestPoolSize());
System.out.println("keepAliveTime:" + es1.getKeepAliveTime(TimeUnit.SECONDS));
Thread.sleep(3000); // 沉睡3s在执行下一个任务. 上一个任务2s就执行完毕了, 但是因为没有达到核心线程数, 还是去创建了新的线程.
}
es1.shutdown();
}
}
class DemoTask implements Runnable {
private int taskNum;
public DemoTask(int taskNum) {
this.taskNum = taskNum;
}
@Override
public void run() {
System.out.println("正在执行" + taskNum);
try {
Thread.sleep(2000);
}catch(InterruptedException ex) {
ex.printStackTrace();
}
System.out.println("执行完毕" + taskNum);
}
}
线程池和核心参数和拒绝策略有哪些?
线程池的构造函数有一些是默认的. 比如测试代码中使用的就是有部分默认的
完整的应该是如下
/**
* Creates a new {@code ThreadPoolExecutor} with the given initial
* parameters and default thread factory.
*
* @param corePoolSize the number of threads to keep in the pool, even
* if they are idle, unless {@code allowCoreThreadTimeOut} is set
* @param maximumPoolSize the maximum number of threads to allow in the
* pool
* @param keepAliveTime when the number of threads is greater than
* the core, this is the maximum time that excess idle threads
* will wait for new tasks before terminating.
* @param unit the time unit for the {@code keepAliveTime} argument
* @param workQueue the queue to use for holding tasks before they are
* executed. This queue will hold only the {@code Runnable}
* tasks submitted by the {@code execute} method.
* @param handler the handler to use when execution is blocked
* because the thread bounds and queue capacities are reached
* @throws IllegalArgumentException if one of the following holds:<br>
* {@code corePoolSize < 0}<br>
* {@code keepAliveTime < 0}<br>
* {@code maximumPoolSize <= 0}<br>
* {@code maximumPoolSize < corePoolSize}
* @throws NullPointerException if {@code workQueue}
* or {@code handler} is null
*/
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
RejectedExecutionHandler handler) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
Executors.defaultThreadFactory(), handler);
}
* @param handler the handler to use when execution is blocked
* because the thread bounds and queue capacities are reached // 当阻塞队列已经满了的时候, 我们应该使用哪些拒绝策略
handler 就是拒绝策略, 简单来说.
默认是会抛出异常, 将demo代码中的size 改成 100 可以看到抛出了一个异常.
1、AbortPolicy:直接抛出异常。
2、CallerRunsPolicy:只用调用者所在线程来运行任务。 -- 简单来说, 就是上述demo的main线程来运行任务.
3、DiscardOldestPolicy:丢弃队列里最老(引用文献使用最近,感觉有问题)的一个任务,并执行当前任务。
4、DiscardPolicy:不处理,丢弃掉。
简单理解:
如果很线程任务涌入的话, 直接奔溃报错.
主线程分配了任务, 我线程池接受不了, 拒绝, 你自己做吧.
新来的任务最重要, 旧的任务我就不做了.
直接丢弃. 不做了.