使用线程池有以下好处:
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.ThreadPoolExecutor.AbortPolicy;
import java.util.concurrent.TimeUnit;
public class Client {
public static void main(String[] args) {
ExecutorService executorService = new ThreadPoolExecutor(
5,
10,
60,
TimeUnit.SECONDS,
new LinkedBlockingQueue<>(),
Executors.defaultThreadFactory(),
new AbortPolicy()
);
executorService
.execute(() -> System.out.println(Thread.currentThread().getName() + " is running"));
executorService.shutdown();
}
}
线程池的核心实现为ThreadPoolExecutor类,
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler) {
}
一共有7大重要参数
表示核心线程数量,线程池中有两种线程,核心线程和非核心线程(临时工)
表示线程总数量,核心数+非核心数
表示非核心线程闲置超时时长,超过了这个时间,线程就会被回收,如果设置了allowCoreThreadTimeOut(true),也会作用于核心线程
时间单位,主要有时(HOURS),分(MINUTES),秒(SECONDS),毫秒(MILLISECONDS),微妙(MICROSECONDS),纳秒(NANOSECONDS)
任务队列,当任务数量超过核心线程数时,就会将任务添加到任务队列中。
常用的队列类型有
1.LinkedBlockingQueue,阻塞队列,底层实现为链表,默认大小为Integer.MAX_VALUE,可以设置大小
2.ArrayBlockingQueue,阻塞队列,底层实现为数组,必须指定大小
3.SynchronousQueue,同步队列,容量为0,添加操作必须等待消费操作,反之亦然
4.DelayQueue,延时队列,只有到达了延时时间,才能从队列中获取到
/**
* The default thread factory.
*/
private static class DefaultThreadFactory implements ThreadFactory {
private static final AtomicInteger poolNumber = new AtomicInteger(1);
private final ThreadGroup group;
private final AtomicInteger threadNumber = new AtomicInteger(1);
private final String namePrefix;
DefaultThreadFactory() {
SecurityManager s = System.getSecurityManager();
group = (s != null) ? s.getThreadGroup() :
Thread.currentThread().getThreadGroup();
namePrefix = "pool-" +
poolNumber.getAndIncrement() +
"-thread-";
}
public Thread newThread(Runnable r) {
Thread t = new Thread(group, r,
namePrefix + threadNumber.getAndIncrement(),
0);
if (t.isDaemon())
t.setDaemon(false);
if (t.getPriority() != Thread.NORM_PRIORITY)
t.setPriority(Thread.NORM_PRIORITY);
return t;
}
}
1.AbortPolicy,直接抛异常
2.DiscardPolicy,直接丢弃,不抛异常
3.DiscardOldestPolicy,丢弃任务队列头部元素,重新尝试执行
4.CallerRunsPolicy,由调用线程来执行
上述7个参数,前5个为必须,后2个非必须。
线程池一共有5种状态,
jdk提供了一个工具类Executors,简化我们创建线程池的过程
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}
不会创建核心线程,全部为非核心线程(临时工),超过60S回收。适合执行有很多短时间的任务。
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>()));
}
只有一个核心线程,和 newFixedThreadPool(1) 的区别为,newFixedThreadPool(1)创建的线程池是可以重新配置的,如重新设置核心线程数量,而newSingleThreadExecutor()创建的线程池不能重新配置。
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
return new ScheduledThreadPoolExecutor(corePoolSize);
}
public ScheduledThreadPoolExecutor(int corePoolSize) {
super(corePoolSize, Integer.MAX_VALUE,
DEFAULT_KEEPALIVE_MILLIS, MILLISECONDS,
new DelayedWorkQueue());
}
ScheduledThreadPoolExecutor继承于ThreadPoolExecutor,支持定时任务及周期性任务。
线程池,这一篇或许就够了
Java线程池实现原理与源码解析(jdk1.8)
原文:https://www.cnblogs.com/strongmore/p/14879439.html