使用线程池执行多线程完毕后的操作

场景:在使用线程池执行多线程之后,获取每个线程获取的数据或是结果的集合,那么在主线程中想要获取完整的集合,就要等子线程执行完毕后,才能获取;

目的:实现子线程执行完毕,再执行子线程;

两种方法:第一种:

ExecutorService executorService = PingVMThreadPool.getInstance().getExecutorService();

//根据list获取具体虚拟机的ip,
for (int i = 0; i < listFromPage.size(); i++) {
PingVMDeploy engine = null;
engine = new PingVMDeploy(listFromPage.get(i).toString());
//线程池提交线程
executorService.submit(engine);
}
//关闭线程池
executorService.shutdown();

while(true){
if(executorService.isTerminated()){判断是否线程关闭
System.out.println("线程结束");
break;
}
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//在线程关闭之后去获取完整的list集合,否则获取的不完整
ArrayList listFromVM = PingVMDeploy.printList();

这个listFromVM集合是根据子线程中的run方法返回的,具体见下面:


 @Override
public void run() {
//这里循环的应该是ip
boolean flag = MyPing.isOk(ip);
if(flag){
arrayList.add(ip);
System.out.println(ip+",,,");
}
}

//获取所有的arraylist
public static ArrayList printList(){
return arrayList;
}

这样我们需要获取的list集合就能完整的获取到,但是这是一次性的,也就是说,这个shutdown执行完毕之后,这个线程池就不能再使用了 ,再次使用的时候,就会出现下面的问题:

再次使用就会报错:

java.util.concurrent.RejectedExecutionException: Task java.util.concurrent.FutureTask@4a85a05 rejected from java.util.concurrent.ThreadPoolExecutor@50848921[Terminated, pool size = 0, active threads = 0, queued tasks = 0, completed tasks = 15]
at java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:2063)
at java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:830)
at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1379)
at java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:112)
at com.cloudmap.csmc.kernel.cloud.svm.service.SVMRegistService.saveInitsvmAdd(SVMRegistService.java:286)
at com.cloudmap.csmc.kernel.cloud.svm.controller.SVMRegistController.saveInitsvmAdd(SVMRegistController.java:172)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.nutz.mvc.impl.processor.MethodInvokeProcessor.process(MethodInvokeProcessor.java:22)
at org.nutz.mvc.impl.processor.AbstractProcessor.doNext(AbstractProcessor.java:44)
at com.cloudmap.csmc.kernel.AccessControlProcessor.process(SourceFile:141)
at org.nutz.mvc.impl.processor.AbstractProcessor.doNext(AbstractProcessor.java:44)
at com.cloudmap.csmc.kernel.logging.LoggingProcessor.process(SourceFile:71)
at org.nutz.mvc.impl.processor.AbstractProcessor.doNext(AbstractProcessor.java:44)
at org.nutz.mvc.impl.processor.AdaptorProcessor.process(AdaptorProcessor.java:33)
at org.nutz.mvc.impl.processor.AbstractProcessor.doNext(AbstractProcessor.java:44)
at org.nutz.mvc.impl.processor.ActionFiltersProcessor.process(ActionFiltersProcessor.java:40)
at org.nutz.mvc.impl.processor.AbstractProcessor.doNext(AbstractProcessor.java:44)
at org.nutz.mvc.impl.processor.ModuleProcessor.process(ModuleProcessor.java:85)
at org.nutz.mvc.impl.processor.AbstractProcessor.doNext(AbstractProcessor.java:44)
at org.nutz.mvc.impl.processor.EncodingProcessor.process(EncodingProcessor.java:27)
at org.nutz.mvc.impl.processor.AbstractProcessor.doNext(AbstractProcessor.java:44)
at org.nutz.mvc.impl.processor.UpdateRequestAttributesProcessor.process(UpdateRequestAttributesProcessor.java:15)
at org.nutz.mvc.impl.NutActionChain.doChain(NutActionChain.java:40)
at org.nutz.mvc.impl.ActionInvoker.invoke(ActionInvoker.java:64)
at org.nutz.mvc.ActionHandler.handle(ActionHandler.java:31)
at org.nutz.mvc.NutFilter.doFilter(NutFilter.java:101)
at com.cloudmap.csmc.CMNutFilter.doFilter(SourceFile:70)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:199)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:493)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:137)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:81)
at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:660)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:798)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:808)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1498)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:748)

这是什么原因?

因为在第一次使用了线程池之后,他就被shutdown了,所以再次调用线程的时候,就会报出这个异常,(报出这个异常有俩原因,可以参考这篇文章 https://blog.csdn.net/zinss26914/article/details/38922449

所以呢,怎么解决?

第一种思路:每次调用,重新new一个线程池

第二种思路:也就是第二种方法,

第二种方法:(不关闭线程池,就是每次子线程执行完毕后都会有一个返回值,这样线程池就不必关闭)

继承callabale:

public class PingVMDeploy2 implements Callable {

private String ip;

public PingVMDeploy2() {
}

public PingVMDeploy2(String ip) {
this.ip = ip;
}

public String getIp() {
return ip;
}

public void setIp(String ip) {
this.ip = ip;
}

@Override
public Object call() throws Exception {
//这里循环的应该是ip
boolean flag = MyPing.isOk(ip);
if(flag){
return ip;
}
return "1";
}
}


主线程:
ArrayList listFromVM = new ArrayList();

for (int i = 0; i < listFromPage.size(); i++) {
PingVMDeploy2 engine = null;
engine = new PingVMDeploy2(listFromPage.get(i).toString());
Future submit = executorService.submit(engine);

try {
if(!submit.get().equals("1")){
listFromVM.add(submit.get());
}
} catch (Exception e) {
e.printStackTrace();
}
}

这样就可以线程池不shutdown的时候获取返回数据;

我不是来改变世界的
原文地址:https://www.cnblogs.com/notchangeworld/p/11365643.html