多線程是java中很重要的知識點,在此小編給大家總結Java Thread多線程,非常有用,希望大家可以掌握哦。
方法一Thread.sleep
#方法二ExecutorService
方法三thread .join
方法四Thread.yield and Thread.activeCount
main 方法運行完畢後其他子執行緒都會關閉, 無法觀察到所有子線程的詳細的運行情況, 於是需要讓主線程等待所有子線程運行完畢後才關閉, 以前比較馬虎的做法就是在
main 函數裡面添加
Thread. sleep(time)
這應該是最常見的方法, 雖然不是最佳的實踐, 但是可以勉強滿足需求.
public static void main(String[] args) throws InterruptedException{ for(int i=0; i<10; i++){ new Thread("subthread" + i){ @Override public void run() { try { Thread.sleep(1000); System.out.println(Thread.currentThread().getName() + "finished"); }catch(InterruptedException e){ e.printStackTrace(); } } }.start(); } Thread.sleep(2000); System.out.println("main thread finished"); }運行結果:
subthread0finished subthread1finished subthread2finished subthread6finished subthread4finished subthread5finished subthread3finished subthread9finished subthread8finished subthread7finished main thread finished方法二ExecutorService可以使用執行緒池實作, 常用的執行緒池物件都是
shutdown 等方法可以保證目前提交的任務在子執行緒上運行完畢後Java進程正常退出.
public static void main(String[] args) { // 创建一个ExecutorService ExecutorService ex = Executors.newCachedThreadPool(); for(int i=0; i<10; i++){ // 添加 task ex.submit(new Thread("subthread" + i){ @Override public void run() { try{ Thread.sleep(1000); System.out.println(Thread.currentThread().getName() + "finished"); }catch(InterruptedException e){ e.printStackTrace(); } } }); } // 使用shutdown 会通知executorservice 停止添加其它task 它会等待所有子线程运行结束才退出Java进程 ex.shutdown(); System.out.println("main thread finished"); }
運行結果為:
main thread finished pool-1-thread-3finished pool-1-thread-4finished pool-1-thread-2finished pool-1-thread-1finished pool-1-thread-5finished pool-1-thread-7finished pool-1-thread-8finished pool-1-thread-6finished pool-1-thread-9finished pool-1-thread-10finished
此種方法有一些小的瑕疵, 我們從輸出的資訊可以看到主線程其實先於子線程運行完畢, 所以這種方法只能夠保證子線程在程序退出之前可以運行完, 但是不能夠保證主線程在子線程運行完畢之後再執行.所以代碼還需要更改,新增一個
awaitTermination(time, timeunit) 設定一個較為合理的等待的時間, 等待子執行緒運行完畢.
public static void main(String[] args) { // 创建一个ExecutorService ExecutorService ex = Executors.newCachedThreadPool(); for(int i=0; i<10; i++){ // 添加 task ex.submit(new Thread("subthread" + i){ @Override public void run() { try{ Thread.sleep(1000); System.out.println(Thread.currentThread().getName() + "finished"); }catch(InterruptedException e){ e.printStackTrace(); } } }); } // 使用shutdown 会通知executorservice 停止添加其它task 它会等待所有子线程运行结束才退出Java进程 ex.shutdown(); try { // 设置等待时间等待子线程运行完毕 if(!ex.awaitTermination(2000, TimeUnit.MILLISECONDS)){ // 等待时间内子线程并未全部运行完毕就直接关闭 ex.shutdownNow(); } }catch(InterruptedException e){ ex.shutdownNow(); } System.out.println("main thread finished"); }
運行結果:
pool-1-thread-1finished pool-1-thread-5finished pool-1-thread-4finished pool-1-thread-9finished pool-1-thread-8finished pool-1-thread-3finished pool-1-thread-2finished pool-1-thread-7finished pool-1-thread-6finished pool-1-thread-10finished main thread finished可以看到主執行緒執行的內容在最後輸出的. 這個方法與方法一一樣都需要設定等待時間, 不是很完美的方法.方法三thread.join
main 執行緒上面建立的, 所以在
main 執行緒裡面執行
某一個子執行緒.join 時會等待子執行緒運行完畢才繼續執行
main 執行緒, 程式碼如下:
public static void main(String[] args) throws InterruptedException{ List<Thread> list = new ArrayList<>(); for(int i=0; i<10; i++){ Thread t = new Thread("subthread" + i){ @Override public void run() { try{ Thread.sleep(3000); System.out.println(Thread.currentThread().getName() + "finished"); }catch(InterruptedException e){ e.printStackTrace(); } } }; list.add(t); t.start(); } for(Thread item : list){ item.join(); } System.out.println("main thread finished"); }
執行結果:
subthread1finished subthread2finished subthread0finished subthread3finished subthread6finished subthread5finished subthread4finished subthread9finished subthread7finished subthread8finished main thread finished使用這個方法相比去上面兩種方法優點在於不用設定等待時間.方法四Thread.yield and Thread.activeCount
首先說明一下這兩個方法的作用,
Thread.yield
放棄
自己佔用CPU 的權利. 但是並不表示當前線程一定不再執行.
Thread.activeCount 方法返回的是當前調用這個線程對應的線程組中所有的活躍線程數量. 在創建線程的時候(new Thread) 其中這個
ThreadGroup
參數指的就是創建線程對應的線程組, 如果這個參數沒有指定, 那麼創建的線程與創建這個線程的線程是同一個線程組. 程式碼如下:
public static void main(String[] args) { // 关键参数 int defaultThreadNum = 2; for(int i=0; i<10 ;i++){ new Thread("subthread" + i){ @Override public void run() { try { Thread.sleep(1000); System.out.println(Thread.currentThread().getName() + "finished"); }catch(InterruptedException e){ e.printStackTrace(); } } }.start(); } while(Thread.activeCount() > defaultThreadNum){ // 当活跃线程数大于设定的默认线程数的时候 主线程让步 Thread.yield(); } System.out.println("main thread finished"); }
運行結果:
subthread0finished subthread4finished subthread1finished subthread8finished subthread9finished subthread5finished subthread2finished subthread3finished subthread6finished subthread7finished main thread finished
有一個很關鍵的地方就是這個
defaultthreadnum 設定的是2. 有一些blog中設定的是1, 但是1會導致無限循環, 主線程無法退出, 原因在於大家都認為主線程所在的線程組中排除子線程後只剩下主線程一個線程了, 其實不然, 比如我們運行如下的代碼:public static void main(String[] args) { Thread.currentThread().getThreadGroup().list(); }輸出:
java.lang.ThreadGroup[name=main,maxpri=10] Thread[main,5,main] Thread[Monitor Ctrl-Break,5,main]
的線程, 因此排除所有子線程後還剩餘2個線程, 所以循環判斷的門限(defaultThreadNum) 需要設定為2.
此方法也是不需要設定等待時間的.綜上所述, 如果需要實作主執行緒在所有子執行緒運行結束後再運行可以使用方法三和方法四.
######### ######相關推薦:############Java Thread多執行緒全面解析###########php5 non -thread-safe和thread-safe的差別######以上是子執行緒任務全部完成後主執行緒關閉的四種方法的詳細內容。更多資訊請關注PHP中文網其他相關文章!