執行邏輯:在當前代碼塊(好比main方法)中的線程A執行了join方法,java
那麼當代碼塊(main)執行到join方法時,會中止繼續向下執行,一直到線程A執行完畢,ide
main方法纔會繼續向下執行。測試
代碼一:網站
package com.thread; import java.util.ArrayList; import java.util.List; import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; import java.util.stream.IntStream; public class ThreadJoin { public static void main(String[] args) throws InterruptedException { Thread thread1=new Thread(new Runnable() { @Override public void run() { for(int i=0;i<5;i++){ System.out.println(Thread.currentThread().getName()+":"+i); } } },"線程1"); Thread thread2=new Thread(new Runnable() { @Override public void run() { for(int i=0;i<5;i++){ System.out.println(Thread.currentThread().getName()+":"+i); } } },"線程2"); //啓動線程1 thread1.start(); //啓動線程2 thread2.start(); /** * 當代碼執行到這一步的時候,程序再也不向下執行,等待thread1執行完畢後向下執行 * 同時thread1和thread2相互掙多cpu調度資源 */ thread1.join(); /** * 當代碼執行到這一步的時候,程序不在向下執行,等待thread2執行完畢後向下執行 * 由於此時的thread1已經執行完畢了,只用thread2執行 */ thread2.join(); for(int i=0;i<2;i++){ System.out.println(Thread.currentThread().getName()+"#"+i); TimeUnit.SECONDS.sleep(1); } } }
使用案例:this
假如如今有一個長途車票銷售網站,想要查詢合肥到上海的汽車;spa
而合肥又有不少的汽車站(合肥1站,合肥2站,合肥3站),同時上海也有不少的汽車站(上海1站,上海2站,上海3站)。線程
這個時候網站平臺須要調用合肥的各個汽車平臺官方的接口來獲取合肥到上海的車票信息。code
正常的同步思惟應該是這樣子的:orm
1.先調用合肥1站到上海站的車票信息,耗時3s,blog
2.調用合肥2站到上海站的車票信息,耗時5s,
3.調用合肥3站到上海站的車票信息,耗時1s。
等這3個接口調用完畢後,組裝返回的參數展現到界面。
有了線程的join方法就能夠同時讓這三個接口去請求接口,等三個接口調用完畢後再組裝參數展現給客戶。
這是總耗時取決於返回接口數據最慢的那一個接口。
Platform.java 車站類
package com.thread.car; import java.util.ArrayList; import java.util.List; /** * 合肥車站1 */ public class PlatForm { private String startCity; private String endCity; public PlatForm(String startCity,String endCity) { this.startCity=startCity; this.endCity=endCity; } private final List<String> list=new ArrayList<>(); public void search(){ this.list.add(this.startCity+"站到"+this.endCity+"1站的信息"); this.list.add(this.startCity+"站到"+this.endCity+"2站的信息"); this.list.add(this.startCity+"站到"+this.endCity+"3站的信息"); } public List<String> get(){ return this.list; } }
Test.java 測試類
package com.thread.car; import java.util.ArrayList; import java.util.List; import java.util.concurrent.TimeUnit; public class Test { /*private static List<String> resList=new ArrayList<>(); private static synchronized void addList(List<String> list){ resList.addAll(list); }*/ public static void main(String[] args) throws InterruptedException { //List<String> list=new ArrayList<String>(); PlatForm pf1=new PlatForm("合肥1","上海"); PlatForm pf2=new PlatForm("合肥2","上海"); PlatForm pf3=new PlatForm("合肥3","上海"); Thread thread1=new Thread(new Runnable() { @Override public void run() { try { pf1.search(); TimeUnit.SECONDS.sleep(5); System.out.println(Thread.currentThread().getName()+"執行結束"); } catch (InterruptedException e) { e.printStackTrace(); } } },"合肥1站"); Thread thread2=new Thread(new Runnable() { @Override public void run() { try { pf2.search(); TimeUnit.SECONDS.sleep(4); System.out.println(Thread.currentThread().getName()+"執行結束"); } catch (InterruptedException e) { e.printStackTrace(); } } },"合肥2站"); Thread thread3=new Thread(new Runnable() { @Override public void run() { try { pf3.search(); TimeUnit.SECONDS.sleep(1); System.out.println(Thread.currentThread().getName()+"執行結束"); } catch (InterruptedException e) { e.printStackTrace(); } } },"合肥3站"); thread1.start(); thread2.start(); thread3.start(); long start=System.currentTimeMillis(); thread1.join(); thread2.join(); thread3.join(); long end=System.currentTimeMillis(); System.out.println((end-start)/1000); List<String> list=new ArrayList<String>(); list.addAll(pf1.get()); list.addAll(pf2.get()); list.addAll(pf3.get()); for(String s:list){ System.out.println(s); } } }