1:自定义线程池注意的点:1:核心线程数:获取当前服务的可用核数。2:一定要声明有界队列。
个人倾向callable而不是runnable, 便于观察线程池的返回值。futrueTask提供一次性添加所有任务,最后一次性提交,支持返回值。
2:是否需要手动调用shutdown:
shutdown会按过去执行已提交任务的顺序发起一个有序的关闭,但是不接受新任务。如果已经关闭,则调用没有其他作用。当Executor已经关闭,并且Executor将有限边界用于最大线程和工作队列容量,且已经饱和时,在方法execute()中提交的新任务将被拒绝。shutdown只是将空闲的线程interrupt()了,因此在shutdown()之前提交的任务可以继续执行直到结束。 如果不shutdown() 池中的线程执行完了之后自然就被销毁了,就跟你不用Executor而自己new一个Thread然后run一样,后续这个线程会自己关闭。
3:CompletionService和ExecutorService,区别在于CompletionService不需要List<Future>来添加任务,其take方法返回已完成的一个Callable任务对应的Future对象,CompletionService的take返回的future是哪个先完成就先返回哪一个,而不是根据提交顺序。
(一):队列满了,捕获异常后,改为同步执行。
package com.job;
import org.springframework.core.task.TaskRejectedException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;
/**
* @Author:
* @Date: 18/8/31 11:50
* @Description: * 线程池的使用-提交任务及获取结果
*/
public class ThreadPoolAction {
private static int totalTask = 100;
private static ThreadPoolAction instance;
private static ThreadPoolAction getInstance() {
if (null == instance) {
instance = new ThreadPoolAction();
}
return instance;
}
/**
* 异步线程池
*/
private CompletionService<Integer> completionService = new ExecutorCompletionService<>(new ThreadPoolExecutor(Runtime.getRuntime().availableProcessors(), 20, 60, TimeUnit.SECONDS, new LinkedBlockingDeque<>(1024)));
/***
* 普通线程池
*/
private ExecutorService executorService = new ThreadPoolExecutor(Runtime.getRuntime().availableProcessors(), 20, 60, TimeUnit.SECONDS, new LinkedBlockingDeque<>(1024));
public static void main(String[] args) {
ThreadPoolAction.getInstance().completeServiceThreadPool();
ThreadPoolAction.getInstance().executorServiceThreadPool();
}
/**
* 相当于executorService + BlockingDeque,方便了获取结果
*/
public void completeServiceThreadPool() {
Long startTime = System.currentTimeMillis();
for (int i = 0; i < totalTask; i++) {
LeBangTask task = new LeBangTask();
try {
completionService.submit(task);
} catch (TaskRejectedException e) {
try {
//队列已满,改为同步执行
task.call();
} catch (Exception e1) {
System.out.println("任务同步执行失败!");
}
}
}
for (int i = 0; i < totalTask; i++) {
try {
System.out.println("线程ID:" + completionService.take().get() + "已经执行完毕!");
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
Long endTime = System.currentTimeMillis();
System.out.println("==任务执行完毕! 总耗时: " + (endTime - startTime) + " ms ==");
}
/**
* 新建线程池
*/
public void executorServiceThreadPool() {
Long startTime = System.currentTimeMillis();
List<Future<Long>> futureList = new ArrayList<>();
for (int i = 0; i < totalTask; i++) {
LeBangTask task = new LeBangTask();
try {
Future<Long> future = executorService.submit(task);
futureList.add(future);
} catch (TaskRejectedException e) {
try {
//队列已满,改为同步执行
task.call();
} catch (Exception e1) {
System.out.println("任务同步执行失败!");
}
}
}
for (Future<Long> future : futureList) {
try {
System.out.println("线程ID:" + future.get() + "已经执行完毕!");
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
Long endTime = System.currentTimeMillis();
System.out.println("==任务执行完毕! 总耗时: " + (endTime - startTime) + " ms ==");
}
class LeBangTask implements Callable {
@Override
public Long call() throws Exception {
//======= 业务逻辑开始 =======
System.out.println("线程ID: " + Thread.currentThread().getId() + "加入执行!");
//======= 业务逻辑结束 =======
return Thread.currentThread().getId();
}
}
}
(二)提供拒绝策略,队列满了阻塞、直到队列有新的空间再插入。
package com..job;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;
/**
* @Author:
* @Date: 18/10/24 20:08
* @Description: *
*/
public class ThreadPoolAction {
private static final Logger LOGGER = LoggerFactory.getLogger(ThreadPoolAction.class);
private static int totalTask = 100;
private static ThreadPoolAction instance;
private static ExecutorService executorService;
private static ThreadPoolAction getInstance() {
if (null == instance) {
instance = new ThreadPoolAction();
}
return instance;
}
static {
RejectedExecutionHandler handler = new RejectedExecutionHandler() {
@Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
try {
executor.getQueue().put(r);
LOGGER.info("队列已满,阻塞直到有空间再插入!");
} catch (InterruptedException e) {
LOGGER.error("执行器InterruptedException,插入队列失败!");
}
}
};
executorService = new ThreadPoolExecutor(15, 20, 3,
TimeUnit.MINUTES, new ArrayBlockingQueue<Runnable>(500), handler);
}
public static void main(String[] args) {
ThreadPoolAction.getInstance().executorServiceThreadPool();
}
/**
* 新建线程池
*/
public void executorServiceThreadPool() {
Long startTime = System.currentTimeMillis();
List<Future<Long>> futureList = new ArrayList<>();
for (int i = 0; i < totalTask; i++) {
LeBangTask task = new LeBangTask();
Future<Long> future = executorService.submit(task);
futureList.add(future);
}
for (Future<Long> future : futureList) {
try {
System.out.println("线程ID:" + future.get() + "已经执行完毕!");
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
Long endTime = System.currentTimeMillis();
System.out.println("==任务执行完毕! 总耗时: " + (endTime - startTime) + " ms ==");
}
class LeBangTask implements Callable {
@Override
public Long call() throws Exception {
//======= 业务逻辑开始 =======
System.out.println("线程ID: " + Thread.currentThread().getId() + "加入执行!");
//======= 业务逻辑结束 =======
return Thread.currentThread().getId();
}
}
}