Listts = new ArrayList<>(); for(int i=0;i<30;i++){ int j = i; Thread tr = new Thread(()->{ try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(j); }); ts.add(tr); // tr.join();//invalid // tr.start(); //阻塞当前线程,这里阻塞启动它的线程 // tr.join();//valid } //先启动 ts.forEach(d->{ d.start(); }); //再阻塞当前线程 //保证线程已经启动,阻塞当前线程保证执行顺序 //和返回结果正确 ts.forEach(d->{ try { d.join(); } catch (InterruptedException e) { e.printStackTrace(); } }); // ThreadUtil.execute(); System.out.println("end");
思路:先执行所有的线程,在调用join阻塞当前线程,等待所有线程执行完,在继续 执行当前线程代码 如果 先start后面立即跟join,就会变成线程顺序执行,跟一个线程执行效果没什么分别, 所以 先启动所有的线程,再分别join 就能保证 线程异步,并且最后所有线程执行完, 再继续执行当前线程最后代码。 反正 start 和 join 关系要理解清楚,就知道为什么先 start 所有,再join所有。 (顺便一说,所有线程执行 join 必是顺序执行的,因为如果线程没执行完,join会阻塞当前线程, 并且 编程语言代码 是顺序 结构 执行的,所有 就会 一个 join 的 一个 join 的执行,要想 写出的代码 能并行 执行,那必须编程语言 可以 对并行的代码的支持 thread 1 ; thread 2 code 1 code 2 一写完马上就可以分别执行,就不用写顺序结构的代码来支持多线程。 ) 错误:先join,后start 是无效的! 注意:Java中如果线程不是后台线程,即使主线程执行完,这个线程仍会继续执行,直到结束。
13 8 11 20 3 4 2 1 0 25 24 26 23 18 17 16 29 28 15 27 10 6 5 22 21 19 14 9 7 12 end



