现在是多核的时代,面向多核的编程很重要,因此基于java的并发和多线程开发非常重要。
线程池是于队列密切相关的,其中队列保存了所有等待执行的任务。工作者线程的任务很简单:从队列中获取一个任务,执行任务,然后返回线程池,等待下一个任务。
在线程池中执行任务,比为每一个任务分配一个线程优势更多:
1.通过重用现在的线程,而不是创建线程,可以在处理多个请求时避免在线程的创建和销毁上的开销。
2.当请求到达时,工作线程通常已经存在,因此不会犹豫等待创建线程而延迟任务的执行,从而提高响应。
3.通过适当的调整线程池的大小,可以创建足够多的线程使处理器保持忙碌状态,同时也可以防止过多线程竞争资源而使应用程序的内存耗尽或失败。
1.配置ThreadPoolExecutor
类库提供了一个灵活的线程池以及一些有用的默认配置,可以通过调用Executors中的静态工厂方法来创建:
newFixedThreadPool:创建一个固定长度的线程池,没提交一个任务就创建一个线程,直到到达线程池的最大数量,这时线程池的规模将不再变化。
newCachedThreadPool:创建一个可缓存的线程池,如果线程的当前规模超过处理的需求时,将回收空闲线程,当需求增加时候,可以添加新的线程,线程池的规模不存在任何限制(不建议使用,如果处理量过多,会因为创建过多线程导致资源耗尽)
newSingleThreadPool: 是一个单线程的Executor。
newScheduledThreadPool:创建一个固定长度的线程池,而且以延迟或者定时的方式来执行。
如果默认的执行策略不满足要求,那么可以通过ThreadPoolExecutor的构造函数来实例化一个对象,并根据自己的需求来定制:
/** * Creates a new {@code ThreadPoolExecutor} with the given initial * parameters. * * @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 threadFactory the factory to use when the executor * creates a new thread * @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 threadFactory} or {@code handler} is null */ public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler)
其中corePoolSize为线程池的基本大小,maximumPoolSize为最大大小。RejectedExecutionHandler为饱和策略,当有界队列被填满之后,采用什么方式来处理。有四种处理方式
如果项目中使用Spring,可以使用spring提供的的线程池管理的包装类ThreadPoolTaskExecutor,它对标准的java.util.concurrent.ThreadPoolExecutor进行了封装,配置和使用比较简单
<bean id="threadPool" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor"> <property name="corePoolSize" value="5" /> <property name="maxPoolSize" value="10" /> <property name="keepAliveSeconds" value="5" /> <property name="queueCapacity" value="2000" /> <property name="rejectedExecutionHandler"> <bean class="java.util.concurrent.ThreadPoolExecutor$AbortPolicy" /> </property> </bean>
corePoolSize:核心线程数,默认为1
maxPoolSize:最大线程数,默认为Integer.MAX_VALUE
keepAliveSeconds:线程池维护线程所允许的空闲时间,默认为60s
queueCapacity:队列最大长度,默认为Integer.MAX_VALUE
rejectedExecutionHandler:线程池对拒绝任务(超过待处理队列长度)的处理策略
AbortPolicy:表示直接抛出RejectedExecutionException异常
使用:
threadPool.execute(new Runnable() { public void run() { try{ ...... }catch(Exception e){ ...... } } });