摘要:的多線程有好幾種,可以繼承,也可以實現接口,還可以實現接口繼承,自己實現方法,就可以定一個線程類,調用就可以在一個新的線程里面調用方法,如果需要等待線程結束,可以調用方法和差不多,只不過不直接繼承,而是實現接口只有一個方法,使用上面用這個去
java 的多線程有好幾種,可以繼承 Thread,也可以實現 Runnable 接口,還可以實現 Callable 接口
Threadclass MyThread extends Thread { private String name; public MyThread(String name) { this.name = name; } @Override public void run() { for (int i = 0; i < 5; i++) { try { Thread.sleep(100L); } catch (Exception e) { e.printStackTrace(); } System.out.printf("%s is running %d ", name, i); } } } { Thread t1 = new MyThread("t1"); Thread t2 = new MyThread("t2"); t1.start(); t2.start(); try { t1.join(); t2.join(); } catch (Exception e) { e.printStackTrace(); } }
繼承 Thread,自己實現 run 方法,就可以定一個線程類,調用 start 就可以在一個新的線程里面調用 run 方法,如果需要等待線程結束,可以調用 join 方法
Runnableclass MyRunnable implements Runnable { private String name; public MyRunnable(String name) { this.name = name; } @Override public void run() { for (int i = 0; i < 5; i++) { try { Thread.sleep(100L); } catch (Exception e) { e.printStackTrace(); } System.out.printf("%s is running %d ", name, i); } } } { Thread r1 = new Thread(new MyRunnable("r1")); Thread r2 = new Thread(new MyRunnable("r2")); r1.start(); r2.start(); try { r1.join(); r2.join(); } catch (Exception e) { e.printStackTrace(); } }
和 Thread 差不多,只不過不直接繼承 Thread,而是實現 Runnable 接口(Runable 只有一個 run 方法),使用上面用這個 Runnable 去構造一個 Thread,這種方式相對直接繼承 Thread 的方式要更加靈活,因為 java 是單繼承,如果繼承了 Thread 就不能再繼承別的類
事實上,建議永遠不要直接繼承 Thread 類,因為從語義上來講,Thread 也應該也只是方法運行的方式,你的類應該是可以在這種方式下運行,而不是一種 Thread 對象,從這個角度講,Runnable 提供了更好的語義,用一個 Thread 對象去運行一個 Runable
Callableclass MyCallable implements Callable{ private Random random; public MyCallable() { this.random = new Random(); } @Override public Integer call() throws Exception { Thread.sleep(100L); return this.random.nextInt(); } } { FutureTask future1 = new FutureTask<>(new MyCallable()); FutureTask future2 = new FutureTask<>(new MyCallable()); new Thread(future1).start(); new Thread(future2).start(); try { System.out.println(future1.get(50, TimeUnit.MILLISECONDS)); } catch (TimeoutException e) { System.out.println("future1 timeout"); } catch (Exception e) { e.printStackTrace(); } try { System.out.println(future2.get()); } catch (Exception e) { e.printStackTrace(); } }
Callable 接口也只有一個方法 call,和 Runnable 不同的是 Callable 允許有返回值,而這個返回值可以通過 FutureTask.get 獲取,還可以設置任務運行的超時時間,超時后會拋出一個異常
ThreadPoolclass MyCallable implements Callable{ private Random random; public MyCallable() { this.random = new Random(); } @Override public Integer call() throws Exception { Thread.sleep(100L); return this.random.nextInt(); } } { ExecutorService es = Executors.newFixedThreadPool(5); Future future1 = es.submit(new MyCallable()); Future future2 = es.submit(new MyCallable()); try { System.out.println(future1.get(50, TimeUnit.MILLISECONDS)); } catch (TimeoutException e) { System.out.println("future1 timeout"); } catch (Exception e) { e.printStackTrace(); } try { System.out.println(future2.get()); } catch (Exception e) { e.printStackTrace(); } es.shutdown(); }
java 里面線程的創建和銷毀成本比較大,所以一般會需要放到線程池里面跑,java 的基礎設施就是好,這些在標準庫里面都有實現,使用上面也很簡單,直接 new 出一個線程池就好了,然后就可以往里面 submit Callable 對象,線程池也有很多種,上面用到的 newFixedThreadPool 是固定線程數的線程池,下面用到的 newCachedThreadPool 在線程不夠用的時候會創建新線程,同時也會不斷復用之前創建的線程
{ ExecutorService es = Executors.newCachedThreadPool(); CompletionServicecs = new ExecutorCompletionService<>(es); cs.submit(new MyCallable()); cs.submit(new MyCallable()); cs.submit(new MyCallable()); cs.submit(new MyCallable()); try { System.out.println(cs.take().get()); System.out.println(cs.take().get()); System.out.println(cs.take().get()); System.out.println(cs.take().get()); } catch (Exception e) { e.printStackTrace(); } es.shutdown(); }
典型的生成者消費者模型里面,我們需要把生產的結果放到一個隊列里面,而消費者從這個隊列里面不斷地去消費,ExecutorCompletionService 就相當于這個隊列,MyCallable 的結果會寫入到緩存里面,使用 cs.take().get() 從里面取出結果
總結線程的創建,銷毀,切換在 java 里面都是耗性能的操作,如果有需求要大量地創建線程,盡量使用線程池去復用線程
參考鏈接測試代碼鏈接:https://github.com/hatlonely/...
“implements Runnable” vs. “extends Thread” :https://stackoverflow.com/que...
轉載請注明出處
本文鏈接:http://hatlonely.com/2018/03/...
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/68835.html
摘要:最近聽很多面試的小伙伴說,網上往往是一篇一篇的多線程的文章,除了書籍沒有什么學習多線程的一系列文章。將此線程標記為線程或用戶線程。 最近聽很多面試的小伙伴說,網上往往是一篇一篇的Java多線程的文章,除了書籍沒有什么學習多線程的一系列文章。但是僅僅憑借一兩篇文章很難對多線程有系統的學習,而且面試的時候多線程這方面的知識往往也是考察的重點,所以考慮之下決定寫一系列關于Java多線程的文章...
摘要:但是并不是什么多線程就可以隨便用,有的時候多線程反而會造成系統的負擔,而且多線程還會造成其他的數據問題,下面就來介紹一下多線程面臨的問題。下面這張圖是多線程運行時候的情況,我們發現上下文切換的次數暴增。 并發的概念: 在Java中是支持多線程的,多線程在有的時候可以大提高程序的速度,比如你的程序中有兩個完全不同的功能操作,你可以讓兩個不同的線程去各自執行這兩個操作,互不影響,不需要執行...
摘要:如圖所示,帶有的所有線程構造方法都可以定義線程組的。線程組還能統一設置組內所有線程的最高優先級,線程單獨設置的優先級不會高于線程組設置的最大優先級。 前面的文章,棧長和大家分享過多線程創建的3種方式《實現 Java 多線程的 3 種方式》。 但如果線程很多的情況下,你知道如何對它們進行分組嗎? 和 Dubbo 的服務分組一樣,Java 可以對相同性質的線程進行分組。 來看下線程類 Th...
摘要:線程可以被稱為輕量級進程。一個守護線程是在后臺執行并且不會阻止終止的線程。其他的線程狀態還有,和。上下文切換是多任務操作系統和多線程環境的基本特征。在的線程中并沒有可供任何對象使用的鎖和同步器。 原文:Java Multi-Threading and Concurrency Interview Questions with Answers 翻譯:并發編程網 - 鄭旭東 校對:方騰飛 多...
摘要:相比與其他操作系統包括其他類系統有很多的優點,其中有一項就是,其上下文切換和模式切換的時間消耗非常少。因為多線程競爭鎖時會引起上下文切換。減少線程的使用。很多編程語言中都有協程。所以如何避免死鎖的產生,在我們使用并發編程時至關重要。 系列文章傳送門: Java多線程學習(一)Java多線程入門 Java多線程學習(二)synchronized關鍵字(1) java多線程學習(二)syn...
摘要:多線程環境下的一些問題安全性問題在沒有正確同步的情況下,多線程環境下程序可能得出錯誤的結果。一些相關概念競爭條件多線程的環境下,程序執行的結果取決于線程交替執行的方式。而線程的交替操作順序是不可預測的,如此程序執行的結果也是不可預測的。 入口 Java多線程的應用復雜性之如jvm有限的幾個內存方面的操作和規范,就像無數紛繁復雜的應用邏輯建立在有限的指令集上。 如何寫出線程安全的程序,有...
閱讀 3513·2021-11-17 17:01
閱讀 3918·2021-11-08 13:12
閱讀 2477·2021-10-08 10:04
閱讀 687·2021-09-29 09:35
閱讀 1418·2021-09-26 10:12
閱讀 2021·2021-09-07 09:58
閱讀 1953·2019-08-30 15:55
閱讀 2134·2019-08-30 13:14