第3条规定:线程资源必须通过线程池提供,不允许在应用中自行显式创建线程
第4条规定:线程池不允许使用Executors创建,而是通过ThreadPoolExecutor的方式创建,这样的处理方式能让编写代码的攻城狮更加明确线程池的运行规则,规避资源耗尽(OOM)的风险
java线程池的使用其实很简单,直接new java.util.concurrent.ThreadPoolExecutor(),这里选择构造参数最多的介绍一下各个入参含义:
//定义线程池
//线程池的基本大小,就是维持线程数
int corePoolSize = 10;
//线程池的最大值
int maximumPoolSize =50;
//超过多长时间对超过基本线程的空闲线程回收
long keepAliveTime = 100L;
//指上面指定时间的单位
TimeUnit unit = TimeUnit.SECONDS;
//线程等待队列,简单定义等待长度
BlockingQueue<Runnable> workQueue = new ArrayBlockingQueue<>(50);
//线程工厂,默认实现
ThreadFactory threadFactory = Executors.defaultThreadFactory();
//线程池的拒绝策略,默认实现
RejectedExecutionHandler handler = new ThreadPoolExecutor.AbortPolicy();
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
corePoolSize,
maximumPoolSize,
keepAliveTime,
unit,
workQueue,
threadFactory,
handler
);
使用就是直接调用execute()方法, 入参为定义的线程,
threadPoolExecutor.execute(new Runnable() {
@Override
public void run() {
System.out.println("这是一个测试线程");
}
});
当然我们可以自定义线程工厂,大部分作用就提供线程命名,方便排查问题,自定义的话就直接向java默认实现类抄作业就行
自定义线程工厂:
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicInteger;
public class MyThreadFactory 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;
MyThreadFactory(String name) {
SecurityManager s = System.getSecurityManager();
group = (s != null) ? s.getThreadGroup() : Thread.currentThread().getThreadGroup();
if (null == name || name.isEmpty()) {
name = "pool";
}
namePrefix = name + "-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.ArrayBlockingQueue:规定大小的BlockingQueue,其构造必须指定大小。其所含的对象是FIFO顺序排序的。
2.LinkedBlockingQueue:大小不固定的BlockingQueue,若其构造时指定大小,生成的BlockingQueue有大小限制,不指定大小,其大小有Integer.MAX_VALUE来决定。其所含的对象是FIFO顺序排序的。
3.PriorityBlockingQueue:类似于LinkedBlockingQueue,但是其所含对象的排序不是FIFO,而是依据对象的自然顺序或者构造函数的Comparator决定。
4.SynchronizedQueue:特殊的BlockingQueue,对其的操作必须是放和取交替完成。
内置了四种拒绝策略,按需求选择:
1.ThreadPoolExecutor.AbortPolicy:丢弃任务并抛出RejectedExecutionException异常。
2.ThreadPoolExecutor.DiscardPolicy:丢弃任务,但是不抛出异常。
3.ThreadPoolExecutor.DiscardOldestPolicy:丢弃队列最前面的任务,然后重新提交被拒绝的任务
4.ThreadPoolExecutor.CallerRunsPolicy:由调用线程(提交任务的线程)处理该任务