-
Executors的简单工厂可以创建多种类型的线程池
(1) newFixedThreadPool
线程池长度固定,每当提交一个任务时就创建一个线程,直到达到线程池的最大数量;如果某个线程抛出未捕捉的Exception,则线程池捕捉一个新的线程
public static ExecutorService newFixedThreadPool(int nThreads) { return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>()); } 或 public static ExecutorService newFixedThreadPool(int nThreads, ThreadFactory threadFactory) { return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>(), threadFactory);
(2) newCachedThreadPool
线程池的规模不存在限制:如果线程池的当前规模超过了处理需求,则回收空闲的线程;如果需求增加,则添加新的线程
public static ExecutorService newCachedThreadPool() { return new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>()); } 或 public static ExecutorService newCachedThreadPool(ThreadFactory threadFactory) { return new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>(), threadFactory); }
(3) newSingleThreadExecutor
创建单个线程来执行任务,并保证任务执行的任何内存写入操作对于后续任务可见,确保按照任务在队列中的顺序来执行
public static ExecutorService newSingleThreadExecutor() { return new FinalizableDelegatedExecutorService (new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>())); } 或 public static ExecutorService newSingleThreadExecutor(ThreadFactory threadFactory) { return new FinalizableDelegatedExecutorService (new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>(), threadFactory)); }
(4) newScheduledThreadPool
创建固定长度的线程池,以延迟或定时的方式执行任务
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) { return new ScheduledThreadPoolExecutor(corePoolSize); } 或 public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize, ThreadFactory threadFactory) { return new ScheduledThreadPoolExecutor(corePoolSize, threadFactory); }
它们有一个共同的特点:就是底层都是用的ThreadPoolExecutor类
ThreadPoolExecutor构造函数的最通用形式
public ThreadPoolExecutor( int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler) { ... } 参数说明
@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
-
线程的创建和销毁
(1) 基本大小corePoolSize
线程池的目标大小,即在没有任务执行时线程池的大小,并且只有在工作队列满了的情况下才会创建超出这个数量的线程
(2) 最大大小maximumPoolSize
可同时活动的线程数量的上限
(3) 存活时间keepAliveTime
如果某个线程的空闲时间超过了存活时间,那么将标记为__可回收__;当线程池的__当前大小超过了基本大小__时,这个线程将被终止
-
管理队列任务
(1) workQueue参数用来管理一个Runnable队列
(2) 队列的排队方法有3种
1° 无界队列
2° 有界队列
3° 同步移交队列 SynchronousQueue
要求:要将一个元素放入SynchronousQueue中,必须有另一个线程正在等待这个元素
注:
使用SynchronousQueue更高效,因为任务会直接移交给执行它的线程,而不是首先放在队列中
-
饱和策略
(1) 应用场景
当__有界队列__被任务__填满__后,接下来到来的任务该如何处理
(2) 饱和策略
1° 中止Abort
直接抛出未检查异常RejectedExecutionException
a. 抛弃Discard
抛弃后来的任务
b. 抛弃最旧的Discard-Oldest
抛弃队列中最前面的任务
2° 调用者运行
把无法放在队列中的任务,返回给调用者,然后在调用者的线程中执行这个任务
这种策略的__主要思想__是:调用者执行这个任务,那么这段时间它就无法提交任务;趁这个时间线程池中的任务有的也可以跑完了
使用示例:
如果服务器过载,主线程就不再accept(),于是到达的请求会在TCP层的队列中等待,然后TCP接收窗口会变小,然后就会让发送方慢点发送
线程池 --> 服务器应用程序 --> 服务器TCP层 --> 客户端TCP层
(3) 饱和策略的设置方式
executor.setRejectExecutionHandler();
或者在构造函数中的handler参数设置
-
线程工厂threadFactory参数
(1) 每当线程池需要创建一个线程时,都是通过threadFactory指定的线程工厂来创建新线程
public interface ThreadFactory { Thread newThread(Runnable r); }
(2) 默认的线程工厂是Executors.defaultThreadFactory(),它会创建一个新的、非守护的线程,不包含任何特殊的配置信息
(3) 为了定制化创建线程,可以自己实现ThreadFactory
示例
MyThreadFactory.java
public class MyThreadFactory implements ThreadFactory { private final String poolName; public MyThreadFactory(String poolName) { this.poolName = poolName; } @Override public Thread newThread(Runnable runnable) { return new MyAppThread(runnable, poolName); } }
MyAppThread.java
public class MyAppThread extends Thread { private static volatile boolean debugLifecycle = false; private static final AtomicInteger created = new AtomicInteger(); private static final AtomicInteger alive = new AtomicInteger(); private static final Logger log = Logger.getAnonymousLogger(); public MyAppThread(Runnable r) { this(r, DEFAULT_NAME); } public MyAppThread(Runnable runnable, String name) { super(runnable, name + "-" + created.incrementAndGet()); super.setUncaughtExceptionHandler( new Thread.UncaughtExceptionHandler() { @Override public void uncaughtException( Thread t, Throwable e) { log.log(Level.SEVERE, "UNCAUGHT in thread " + t.getName(), e); } }); } public void run() { // Copy debug flag to ensure consistent value throughout. boolean debug = debugLifecycle; if (debug) { log.log(Level.FINE, "Created " + getName()); } try { alive.incrementAndGet(); super.run(); } finally { alive.decrementAndGet(); if (debug) { log.log(Level.FINE, "Exiting " + getName()); } } } public static int getThreadsCreated() { return created.get(); } public static int getThreadsAlive() { return alive.get(); } public static boolean getDebug() { return debugLifecycle; } public static void setDebug(boolean b) { debugLifecycle = b; } }
将MyThreadFactory作为参数,每次线程池需要创建线程时,会new一个MyAppThread类型的Thread,MyAppThread定制化添加了Log、统计MyAppThread线程数量等功能
-
调用构造函数后再定制ThreadPoolExecutor的方法
(1) 如果已经调用过ThreadPoolExecutor的构造函数,那么可以用ThreadPoolExecutor的setXXX方法进行设置
(2) 如果是通过Executors的工厂方法创建的ThreadPoolExecutor,它的类型是ExecutorService,这时可以判断一下再set
ExecutorService exec = Executors.newCachedThreadPool(); if ( exec instanceof ThreadPoolExecutor) { ((ThreadPoolExecutor)exec).setCorePoolSize(10); } else { throw new AssertionError("Bad assumption"); }
chapter08_线程池的使用_3_配置ThreadPoolExecutor
最新推荐文章于 2020-08-05 15:52:59 发布