1.任务执行
1.线程中任务执行的方式
1.在单个线程中串行地执行各种任务。缺点:串行处理机制无法提供高吞吐率和快速响应性。
2.显示的为任务创建线程,为一个请求创建一个线程来提供服务。缺点:大量创建线程会存在很多问题,比如:
线程生命周期的开销很高:线程的创建和销毁是需要代价的;资源消耗:活跃的线程会消耗内存,而且会和其它线程竞争资源,产生性能开销;
稳定性:创建大量的线程可能会导致OutOfMemoryError.
2.Executor框架
public interface Executor {
void execute(Runnable command);
}
Runnable表示任务,它将任务的提交过程和执行过程解耦开来。
1.线程池
通过重用现有的线程而不是重新创建新的线程,可以在处理多个请求时分摊在线程创建和销毁过程中产生的巨大开销。
创建线程池的方法:通过调用Executors中不同的静态工厂方法来创建不同的线程。如下:
- newFixedThreadPool:创建固定大小的线程池。每提交一个任务创建一个线程,直到最大值。
public static ExecutorService newFixedThreadPool(int nThreads, ThreadFactory threadFactory) { return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>(), threadFactory); }
- newCachedThreadPool:创建一个可缓存的线程池,如果线程池的当前规模超过了处理需求时,将回收空闲线程;需求增加时增加添加新的线程,线程池
的规模不受任何限制。
public static ExecutorService newCachedThreadPool(ThreadFactory threadFactory) { return new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>(), threadFactory); }
- newScheduledThreadPool:创建一个固定长度的线程池,而且一延迟或定时的方式执行。(类似timer)
public static ScheduledExecutorService newScheduledThreadPool( int corePoolSize, ThreadFactory threadFactory) { return new ScheduledThreadPoolExecutor(corePoolSize, threadFactory); }
2.Executor的生命周期
Executor扩展了ExecutorService接口,添加了一些用于管理生命周期的方法。ExecutorService生命周期有三种状态:运行、关闭和已终止。 ExecutorService在初始创建时处于运行状态;shutdown方法执行平缓的关闭(不接受新任务和等待已提交的任务执行完成); shutdownNow执行粗暴的关闭(取消所有运行的任务,不再启动队列中的任务);所有任务完成就进入终止状态,或调用awaitTermination方法.
3.配置ThreadPoolExecutor
ThreadPoolExecutor为一些Executor提供了基本的实现,比如上面的那三个的返回值类型就是一个ThreadPoolExecutor。如果默认的执行策略不满足 就可以自己创建。
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler) {
...}
corePoolSize:线程池的基本大小。没有任务执行时,线程的基本大小。
maximumPoolSize:线程池可以活动的最大线程数量。
keepAliveTime:线程存活时间,存活时间到了将被标记,如果当前线程数量超过了基本大小就会被回收。
newFixedThreadPool它的corePoolSize和maximumPoolSize相同;newCachedThreadPool的corePoolSize为0,最大值为Integer.MAX_VALUE.
1.管理任务队列
如果新请求的任务到达速率超过了线程池的处理速率,新来的请求就会累积起来,线程池会把他们放在Executor的Runnable队列中等待。队列有三种: 无界队列、有界队列和同步移交。newFixedThreadPool采用了无界队列、newCachedThreadPool采用同步移交,有界队列满了(饱和)后可以使用饱和策略: 中止(抛出异常)、调用者运行(将任务退回到调用者)。
2.线程工厂
每当线程池需要创建一个线程时,都是通过线程工厂方法来完成的。默认的线程工厂方法(Executors.defaultThreadFactory()
)会创建一个新的、非守护
的线程,并且不包含特殊的配置信息。用户可以自己指定线程工厂方法,定制线程的配置信息,比如指定线程名字等。
public interface ThreadFactory {
Thread newThread(Runnable r);
}