线程池的使用可以实现线程的重用,大大节省了系统资源,优化了系统性能。前面讲过线程池的实现原理和源代码分析。基础篇--------浅谈JAVA线程池(源码解析)有兴趣的小伙伴欢迎查看。本章就记录一下线程池使用的五种方式,也可以说是6种。
下方内容所有源码:https://download.csdn.net/download/u011909918/11505361
小板凳搬过来坐好。
先上周边代码,自定义线程,自定义线程池中超出队列大小之后提交任务处理机制(等一段时间提交)
/**
* 线程工厂,用于提交任务给线程池
*/
static class MyTherd implements Runnable {
private String message;
public MyTherd(String message) {
this.message = message;
}
@Override
public void run() {
//此处实现业务逻辑
}
}
/**
* 线程池队列中任务超出最大数量处理机制
*/
static class MyHandler implements RejectedExecutionHandler{
@Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
try {
logger.info("MQLitener: current threads count is: " + executor.getActiveCount());
Thread.sleep(3000); //等待3S,消息队列有空闲,重新提交
executor.execute(r);
}catch (Exception e){
logger.error("MQLitener: RejectedExecutionHandler Error", e);
}
}
}
/**
* 代码入口
*/
public static void main(String[] args) {
String message = "";
executor.execute(new MyTherd(message));
}
创建线程池(Create Thread pool):
----------------------------------------废话不多说,直接上代码--------------------------------------------------
Method one(原始创线程池):
private static Integer corePoolSize = 70; //最大核心线程数
private static Integer maximumPoolSize = 100; //最大线程数
private static Integer keepAliveTime = 10; //线程允许空闲时间
private static Integer maxQueueSize = 500; //阻塞队列最大数量
//线程池
private static ExecutorService executor = new ThreadPoolExecutor(corePoolSize, //核心线程数
maximumPoolSize, //最大线程数
keepAliveTime,
TimeUnit.SECONDS, //线程允许空闲时间单位
new ArrayBlockingQueue<>(maxQueueSize, true), //线程池阻塞队列, 也可以用LinkedBlockingQueue等其他队列
new MyHandler());
corePoolSize ------------消息队列不超过maxQueueSize 时可以创建的最大线程数;
maximumPoolSize --------------消息队列超过maxQueueSize时会创建新的线程知道达到最大线程数;
maxQueueSize -----------消息队列中可以保存的最大消息数量
keepAliveTime -----------无任务执行时线程存活时间
注意:下面的方式不建议在线上使用,因为它们的消息队列都是无界的。
Method two(缓存线程池):
//创建缓存线程池-----不限制线程数量,只要机器资源足够,进来一个任务,创建一个线程(看下面源码)
private static ExecutorService executor = Executors.newCachedThreadPool();
这个源码是这样的,根据Method one 自行理解:
/**
* Creates a thread pool that creates new threads as needed, but
* will reuse previously constructed threads when they are
* available. These pools will typically improve the performance
* of programs that execute many short-lived asynchronous tasks.
* Calls to {@code execute} will reuse previously constructed
* threads if available. If no existing thread is available, a new
* thread will be created and added to the pool. Threads that have
* not been used for sixty seconds are terminated and removed from
* the cache. Thus, a pool that remains idle for long enough will
* not consume any resources. Note that pools with similar
* properties but different details (for example, timeout parameters)
* may be created using {@link ThreadPoolExecutor} constructors.
*
* @return the newly created thread pool
*/
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}
Method three(定长线程池):
//创建定长线程池 线程池的最大核心线程数和最大线程数相等且固定,为入参
private static ExecutorService executor = Executors.newFixedThreadPool(corePoolSize);
这个源码是这样的,根据Method one 自行理解:
/**
* Creates a thread pool that reuses a fixed number of threads
* operating off a shared unbounded queue. At any point, at most
* {@code nThreads} threads will be active processing tasks.
* If additional tasks are submitted when all threads are active,
* they will wait in the queue until a thread is available.
* If any thread terminates due to a failure during execution
* prior to shutdown, a new one will take its place if needed to
* execute subsequent tasks. The threads in the pool will exist
* until it is explicitly {@link ExecutorService#shutdown shutdown}.
*
* @param nThreads the number of threads in the pool
* @return the newly created thread pool
* @throws IllegalArgumentException if {@code nThreads <= 0}
*/
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
Method four(单例线程池):
//创建单例线程池 线程池中只有一个线程只执行任务,其他任务都在排队
private static ExecutorService executor = Executors.newSingleThreadExecutor();
这个源码是这样的,根据Method one 自行理解:
/**
* Creates an Executor that uses a single worker thread operating
* off an unbounded queue. (Note however that if this single
* thread terminates due to a failure during execution prior to
* shutdown, a new one will take its place if needed to execute
* subsequent tasks.) Tasks are guaranteed to execute
* sequentially, and no more than one task will be active at any
* given time. Unlike the otherwise equivalent
* {@code newFixedThreadPool(1)} the returned executor is
* guaranteed not to be reconfigurable to use additional threads.
*
* @return the newly created single-threaded Executor
*/
public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>()));
}
Method five(任务线程池):
//创建定长可执行任务线程池
private static ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(corePoolSize);
//创建单例可执行任务线程池
private static ScheduledExecutorService singleThreadScheduledExecutor = Executors.newSingleThreadScheduledExecutor();
public static void main(String[] args) {
String message = "";
//定时任务线程池的使用,singleThreadScheduledExecutor同理
scheduledThreadPool.execute(new MyTherd(message)); //普通使用
scheduledThreadPool.schedule(new MyTherd(message), 2, TimeUnit.SECONDS); //延迟两秒执行
scheduledThreadPool.scheduleAtFixedRate(new MyTherd(message), 2, 4, TimeUnit.SECONDS); //延迟两秒每4秒执行一次
}
这个源码是这样的:
/*******************创建,返回结果ScheduledExecutorService **********************/
/**
* Creates a thread pool that can schedule commands to run after a
* given delay, or to execute periodically.
* @param corePoolSize the number of threads to keep in the pool,
* even if they are idle
* @return a newly created scheduled thread pool
* @throws IllegalArgumentException if {@code corePoolSize < 0}
*/
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
return new ScheduledThreadPoolExecutor(corePoolSize);
}
/**
* Creates a single-threaded executor that can schedule commands
* to run after a given delay, or to execute periodically.
* (Note however that if this single
* thread terminates due to a failure during execution prior to
* shutdown, a new one will take its place if needed to execute
* subsequent tasks.) Tasks are guaranteed to execute
* sequentially, and no more than one task will be active at any
* given time. Unlike the otherwise equivalent
* {@code newScheduledThreadPool(1)} the returned executor is
* guaranteed not to be reconfigurable to use additional threads.
* @return the newly created scheduled executor
*/
public static ScheduledExecutorService newSingleThreadScheduledExecutor() {
return new DelegatedScheduledExecutorService
(new ScheduledThreadPoolExecutor(1));
}
/*******************************使用********************************************/
/**
* Creates and executes a periodic action that becomes enabled first
* after the given initial delay, and subsequently with the given
* period; that is executions will commence after
* {@code initialDelay} then {@code initialDelay+period}, then
* {@code initialDelay + 2 * period}, and so on.
* If any execution of the task
* encounters an exception, subsequent executions are suppressed.
* Otherwise, the task will only terminate via cancellation or
* termination of the executor. If any execution of this task
* takes longer than its period, then subsequent executions
* may start late, but will not concurrently execute.
*
* @param command the task to execute
* @param initialDelay the time to delay first execution
* @param period the period between successive executions
* @param unit the time unit of the initialDelay and period parameters
* @return a ScheduledFuture representing pending completion of
* the task, and whose {@code get()} method will throw an
* exception upon cancellation
* @throws RejectedExecutionException if the task cannot be
* scheduled for execution
* @throws NullPointerException if command is null
* @throws IllegalArgumentException if period less than or equal to zero
*/
public ScheduledFuture<?> scheduleAtFixedRate(Runnable command,
long initialDelay,
long period,
TimeUnit unit);
/**
* Creates and executes a one-shot action that becomes enabled
* after the given delay.
*
* @param command the task to execute
* @param delay the time from now to delay execution
* @param unit the time unit of the delay parameter
* @return a ScheduledFuture representing pending completion of
* the task and whose {@code get()} method will return
* {@code null} upon completion
* @throws RejectedExecutionException if the task cannot be
* scheduled for execution
* @throws NullPointerException if command is null
*/
public ScheduledFuture<?> schedule(Runnable command,
long delay, TimeUnit unit);
OK,上面就是线程池的花式使用方式,与君共勉~