提交一个任务到线程池中,线程池的处理流程如下:
1、判断线程池里的核心线程是否都在执行任务,如果不是(核心线程空闲或者还有核心线程没有被创建)则创建一个新的工作线程来执行任务。如果核心线程都在执行任务,则进入下个流程。
2、线程池判断工作队列是否已满,如果工作队列没有满,则将新提交的任务存储在这个工作队列里。如果工作队列满了,则进入下个流程。
3、判断线程池里的线程是否都处于工作状态,如果没有,则创建一个新的工作线程来执行任务。如果已经满了,则交给饱和策略来处理这个任务。
public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,BlockingQueue workQueue,RejectedExecutionHandler handler)
corePoolSize:线程池核心线程数量
maximumPoolSize:线程池最大线程数量
keepAliverTime:当活跃线程数大于核心线程数时,空闲的多余线程最大存活时间
unit:存活时间的单位
workQueue:存放任务的队列
handler:超出线程范围和队列容量的任务的处理程序
当队列和线程池都满了,说明线程池处于饱和状态,那么必须对新提交的任务采用一种特殊的策略来进行处理。这个策略默认配置是AbortPolicy,表示无法处理新的任务而抛出异常。JAVA提供了4中策略:
1、AbortPolicy:直接抛出异常
2、CallerRunsPolicy:只用调用所在的线程运行任务
3、DiscardOldestPolicy:丢弃队列里最近的一个任务,并执行当前任务。
4、DiscardPolicy:不处理,丢弃掉。
1、 RejectedExecutionHandler handler = new ThreadPoolExecutor.DiscardPolicy();
ThreadPoolExecutor threadPool = new ThreadPoolExecutor(2, 5, 60, TimeUnit.SECONDS, queue,handler);
2、 ThreadPoolExecutor threadPool = new ThreadPoolExecutor(2, 5, 60, TimeUnit.SECONDS, queue);
threadPool.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy());
package com.demo;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ThreadPoolDemo {
int i = 0;
public static void main(String[] args) {
ExecutorService singlePool = Executors.newSingleThreadExecutor();
RunnableService runnableService = new RunnableService("张三" , 5000);
// Thread t1=new Thread(runnableService);
singlePool.execute(runnableService);
ExecutorService fixedPool = Executors.newFixedThreadPool(2);
ThreadService threadService = new ThreadService("lisi" , 2000);
// Thread t2=new Thread(threadService);
fixedPool.execute(threadService);
fixedPool.execute(runnableService);
System.out.println("线程执行完毕");
ExecutorService cachePool = Executors.newCachedThreadPool();
cachePool.execute(threadService);
cachePool.execute(runnableService);
ExecutorService schedualPool = Executors.newScheduledThreadPool(5);
schedualPool.execute(threadService);
schedualPool.execute(runnableService);
}
}
测试线程
class ThreadService extends Thread {
private String name;
private int sleep_second;
public ThreadService(String name , int sleep_second) {
super();
this.name = name;
this.sleep_second = sleep_second;
}
@Override
public void run() {
try {
Thread.sleep(sleep_second);
System.out.println("ThreadService = " + name+"线程sleep了" + sleep_second/1000 + "s");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
测试线程2
class RunnableService implements Runnable {
private String name;
private int sleep_second;
public RunnableService(String name , int sleep_second) {
super();
this.name = name;
this.sleep_second = sleep_second;
}
@Override
public void run() {
try {
Thread.sleep(2000);
System.out.println("RunnableService = "+name+"线程sleep了" + sleep_second/1000 + "s");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
(1) newCachedThreadPool
创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程,线程池为无限大,当执行第二个任务时第一个任务已经完成,会复用执行第一个任务的线程,而不用每次新建线程。
(2) newFixedThreadPool
创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。因为线程池大小为2,每个任务输出index后sleep 2秒,所以每两秒打印。定长线程池的大小最好根据系统资源进行设置。如Runtime.getRuntime().availableProcessors()
(3) newScheduledThreadPool
创建一个定长线程池,支持定时及周期性任务执行。延迟执行
(4) newSingleThreadExecutor
创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。
1、线程是稀缺资源,使用线程池可以减少创建和销毁线程的次数,每个工作线程都可以重复使用。
2、可以根据系统的承受能力,调整线程池中工作线程的数量,防止因为消耗过多内存导致服务器崩溃。