1、线程池:
- 防止大量执行异步任务时,频繁的创建和销毁线程对象带来的系统开销;
- 根据线程池类型的不同可以有效防止系统中的线程资源消耗过多;
2、线程池核心参数:
- corePoolSize:线程池核心线程个数(包括空闲线程)
- maximunPoolSize:线程池中线程的最大数量
- workQueue:存放execute方法提交的任务的阻塞队列(BlockingQueue),如:
synchronousBlockingQueue、ArrayBlockingQueue、LinkedBlockingQueue等。
- ThreadFactory:创建线程的工厂
- keepAliveTime:线程池中线程数量超过corePoolSize时,池中空闲线程的存活时间
- unit:keepAliveTime的单位
- RejectExecutionHandler:任务拒绝策略
3、类结构:
4、常见线程池的种类:
- newSingleThreadExecutor()
- newFixedThreadPool(n)
- newCachedThreadPool()
- newScheduledThreadPool()
注:以上几种线程池类型均是由于设置的corePoolSize、maximunPoolSize、workQueue类型
以及RejectExecutionHandler产生的结果。
5、线程池的状态(volatile int runState):
static final int RUNNING = 0;//运行状态
static final int SHUTDOWN = 1;//显式执行shutdown()方法后的状态,仍会执行完所有
workQueue中的所有任务
static final int STOP = 2;//显式调用shutDownNow()方法后的状态,workQueue中的任
务不再执行且尝试终止正在执行的任务
static final int TERMINATED = 3;//所有任务执行完毕,线程池中的全部工作线程销毁完毕
6、线程池的核心方法:
execute()
submit()
shutdown()
shutdownNow()
7、任务缓存策略:
- 立即提交策略:使用synchronousBlockingQueue工作队列,execute方法执行提交的任务不
会缓存提交的任务,直接在创建线程执行,要求maximumPoolSize足够大。
- 无界队列策略:使用LinkedBlockingQueue工作队列,任务被提交时如果线程池中的线程数
小于corePoolSize时,直接创建线程执行;如果线程数 >= corePoolSize时,
优先向工作队列中添加,等待工作线程执行,如:newFixedThreadPool
- 有界队列策略:使用ArrayBlockingQueue工作队列,当任务队列已满且线程数已达到最大值
选择丢弃任务。
8、任务拒绝策略:
- ThreadPoolExecutor.AbortPolicy:丢弃任务并抛出RejectedExecutionException异常
- ThreadPoolExecutor.DiscardPolicy:也是丢弃任务,但是不抛出异常。
- ThreadPoolExecutor.DiscardOldestPolicy:丢弃队列最前面的任务,然后重新尝试执行任务(重复此过程)
- ThreadPoolExecutor.CallerRunsPolicy:由调用线程处理该任务
9、测试代码:
(1)newSingleThreadExecutor:
public class ThreadPoolTest {
public static void main(String[] args){
ExecutorService executor = Executors.newSingleThreadExecutor();
MyThread thread0 = new MyThread();
MyThread thread1 = new MyThread();
MyThread thread2 = new MyThread();
executor.execute(thread0);
executor.execute(thread1);
executor.execute(thread2);
System.out.println("线程池状态改变");
}
static class MyThread implements Runnable{
@Override
public void run() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName());
}
}
}
执行结果:
线程池状态改变
pool-1-thread-1
pool-1-thread-1
pool-1-thread-1
可以看到所有的任务是由同一个线程执行的。
(2)newFixedThreadPool():
public class ThreadPoolTest {
public static void main(String[] args){
ThreadPoolExecutor executor = (ThreadPoolExecutor)(Executors.newFixedThreadPool(3));
MyThread thread0 = new MyThread();
MyThread thread1 = new MyThread();
MyThread thread2 = new MyThread();
MyThread thread3 = new MyThread();
MyThread thread4 = new MyThread();
executor.execute(thread0);
System.out.println(executor.getPoolSize());
executor.execute(thread1);
System.out.println(executor.getPoolSize());
executor.execute(thread2);
System.out.println(executor.getPoolSize());
executor.execute(thread3);
System.out.println(executor.getPoolSize());
executor.execute(thread4);
System.out.println(executor.getPoolSize());
executor.shutdown();
System.out.println("线程池状态改变");
}
static class MyThread implements Runnable{
@Override
public void run() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName());
}
}
}
执行结果:
1
2
3
3
3
线程池状态改变
pool-1-thread-1
pool-1-thread-2
pool-1-thread-3
pool-1-thread-1
pool-1-thread-2
可以看到线程池中的线程数最多保持在3个。
(3)newCachedThreadPool():
public class ThreadPoolTest {
public static void main(String[] args){
ThreadPoolExecutor executor = (ThreadPoolExecutor)(Executors.newCachedThreadPool());
MyThread thread0 = new MyThread();
MyThread thread1 = new MyThread();
MyThread thread2 = new MyThread();
MyThread thread3 = new MyThread();
MyThread thread4 = new MyThread();
executor.execute(thread0);
System.out.println(executor.getPoolSize());
executor.execute(thread1);
System.out.println(executor.getPoolSize());
executor.execute(thread2);
System.out.println(executor.getPoolSize());
executor.execute(thread3);
System.out.println(executor.getPoolSize());
executor.execute(thread4);
System.out.println(executor.getPoolSize());
executor.shutdown();
System.out.println("线程池状态改变");
}
static class MyThread implements Runnable{
@Override
public void run() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName());
}
}
}
执行结果:
1
2
3
4
5
线程池状态改变
pool-1-thread-1
pool-1-thread-2
pool-1-thread-3
pool-1-thread-4
pool-1-thread-5
可以从结果看到每一个任务都是由不同的线程执行的。