第一个问题:如果使用文件引入,会导致线程不执行,需要使用内部类,我使用的是spring boot
第二个问题:获取返回值的时候,使用Callable的cell方法,可以设置返回值,不过我直接使用future.get()导致线程阻塞了,后来改成了CompletionService方法。
记录一下自己第一次使用多线程。
参考:https://blog.youkuaiyun.com/u011734144/article/details/52351841
第一个:使用内部类方式,执行没有返回值的多线程
public static void main(String[] args) { Test test = new Test(); //没有返回值的多线程 test.runTask(); }
/** * 使用内部类,注入服务 */ class ThirdDataTask implements Runnable{ private int i; public ThirdDataTask(int i) { this.i = i; } @Override public void run() { System.out.println("开始执行:"+ Thread.currentThread().getName()); try { Thread.sleep(1000); System.out.println("执行中:"+ Thread.currentThread().getName()); } catch (Exception e) { System.out.println("执行失败:"+ Thread.currentThread().getName()); e.printStackTrace(); } System.out.println("执行结束:"+ Thread.currentThread().getName()); } } public void runTask(){ ExecutorService executorService = Executors.newFixedThreadPool(10); for (int i = 1; i < 20; i++) { executorService.execute(new ThirdDataTask(i)); } executorService.shutdown(); }
第二个,根据需要更换成有返回值的多线程(线程全部执行完再获取结果)
public static void main(String[] args) { Test test = new Test(); //没有返回值的多线程 test.runTask(); //有返回值的多线程 test.runTask2(); } public void runTask2(){ Integer aa = 0; try { ExecutorService executorService = Executors.newCachedThreadPool(); CompletionService<Integer> completionService = new ExecutorCompletionService<Integer>(executorService); for (int i = 1; i < 20; i++) { System.out.println("开始执行" + i); completionService.submit(getTask(i)); System.out.println("开始结束" + i); } executorService.shutdown(); while (true) { if (executorService.isTerminated()) { System.out.println("所有的子线程都结束了!"); break; } try { Thread.sleep(1000); } catch (InterruptedException e) { System.out.println("处理异常"); } } for (int i = 1; i < 20; i++) { try { Integer taskResult = completionService.take().get(); aa += taskResult; } catch (InterruptedException e) { System.out.println("执行错误"); } catch (ExecutionException e) { System.out.println("执行错误"); } } System.out.println(aa); } finally { System.out.println("执行后的结果" + aa); } } public static Callable<Integer> getTask(int i) { Callable<Integer> task = new Callable<Integer>() { @Override public Integer call() throws Exception { try { Thread.sleep(1000); if(i%13 == 0){ throw new NullPointerException("第"+i +"个数据执行报错了"); } System.out.println("执行中:"+ Thread.currentThread().getName()); return i; }catch (Exception e) { System.out.println("执行失败:"+ Thread.currentThread().getName()); // 返回值可以设置为String类型,返回异常信息 return 0; } } }; return task; }
出现的问题:调用了两次获取返回值的方法,导致程序终止了。
for (int i = 0; i < list.size(); i++) { try { //我在这里获取了两次completionService.take().get();导致最后一次循环时,直接终止了程序。
Integer taskResult = completionService.take().get(); aa += completionService.take().get(); } catch (InterruptedException e) { System.out.println("执行错误"); } catch (ExecutionException e) { System.out.println("执行错误"); }
}
第三个,把线程改成边执行边获取结果,不阻塞,只需要把获取返回值的代码放在executorService.shutdown();前面就可以了。

本文记录了在Spring Boot中使用多线程遇到的挑战。首先,使用文件引入时发现线程未执行,解决方案是采用内部类。其次,通过Callable解决返回值问题,但直接使用Future.get()造成线程阻塞,最终采用CompletionService避免阻塞。最后,调整代码实现边执行边获取结果,防止程序提前终止。

被折叠的 条评论
为什么被折叠?



