摘要:線程執行框架啟動線程將要多線程執行的任務封裝為一個對象將其傳給一個執行框架對象從線程池中選擇線程執行工作任務。
為什么需要執行框架呢?
使用一般的new方法來創建線程有什么問題呢?一般的new線程的方式一般要給出一個實現了Runnable接口的執行類,在其中重寫run()方法,然后再在將這個執行類的對象傳給線程以完成初始化,這個過程中線程的定義和執行過程其實是雜糅在一起了,而且每次new一個新的線程出來在資源上很有可能會產生不必要的消耗,因此我們通過多線程執行框架來解決這兩個問題,其一可以分離線程的定義和執行過程,其二可以通過線程池來動態地管理線程以減小不必要的資源開銷。
線程執行框架啟動線程
將要多線程執行的任務封裝為一個Runnable對象,將其傳給一個執行框架Executor對象, Executor從線程池中選擇線程執行工作任務。
創建多線程框架對象調用線程執行任務
我們通常通過Executors類的一些靜態方法來實例化Executor或ThreadPoolExecutor對象:
比如Executor對象來執行:
public class ThreadTest { public static void main(String[] args) { Executor executor = Executors.newSingleThreadExecutor(); executor.execute(new MyRunnable()); } } class MyRunnable implements Runnable { @Override public void run() { System.out.println("running"); } }
比如線程池的Executor對象來執行:
public class ThreadTest { public static void main(String[] args) { ThreadPoolExecutor executor = (ThreadPoolExecutor) Executors .newFixedThreadPool(3); executor.execute(new MyRunnable()); } } class MyRunnable implements Runnable { @Override public void run() { System.out.println("running"); } }
Executors. newSingleThreadExecutor():一 個線程死掉后,自動重新創建后一個新的線程,所以沒有線程池的概念,不能被ThreadPoolExecutor接收;
Executors. newFixedThreadPool():固定數目的線程池;
Executors. newCachedThreadPool():動態地增加和減少線程數;
多線程框架對象調用線程執行任務取回結果
實現了Runnable接口的執行類雖然可以在run()方法里寫入執行體,但是無法返回結果值,因為run()方法是void型的,而Callable接口解決了這個問題,在繼承了Callable接口的執行類中重寫call()方法可以設置返回值,當Executor對象使用submit()函數提交執行類的時候會由線程池里的線程來運行,運行得到的返回值可以使用Future
public class ThreadTest { public static void main(String[] args) throws InterruptedException, ExecutionException { ThreadPoolExecutor executor = (ThreadPoolExecutor) Executors .newCachedThreadPool(); MyCallable myCallable = new MyCallable(2); Futureresult = executor.submit(myCallable); System.out.println(result.get()); } } class MyCallable implements Callable { private int num; public MyCallable(int num) { this.num = num; } @Override public Integer call() throws Exception { return num * 2; } }
多線程框架對象調用線程執行任務完成第一個還是全部完成就取回結果
使用submit()函數取回的結果不能控制任務是完成第一個還是全部完成就取回結果,然而使用invokeAny()和invokeAll()函數即可獲得這樣的效果,將執行體對象放入集合中傳入這兩個函數,前者可以在完成任務的多線程有一個(第一個)完成時就返回結果,因此結果類型是單結果,而后者則需要等待所有執行任務的線程都執行完畢才返回結果,因此結果仍是集合。
1.invokeAny():
public class ThreadTest { public static void main(String[] args) throws InterruptedException, ExecutionException { ThreadPoolExecutor executor = (ThreadPoolExecutor) Executors.newFixedThreadPool(5); Listcallables = new ArrayList<>(); for(int i=0;i<10;i++){ MyCallable myCallable = new MyCallable(i); callables.add(myCallable); } Integer res = executor.invokeAny(callables); System.out.println(res); } } class MyCallable implements Callable { private int num; public MyCallable(int num) { this.num = num; } @Override public Integer call() throws Exception { System.out.println(Thread.currentThread().getName() + " is running"); return num * 2; } }
2.invokeAll():
public class ThreadTest { public static void main(String[] args) throws InterruptedException, ExecutionException { ThreadPoolExecutor executor = (ThreadPoolExecutor) Executors .newFixedThreadPool(5); Listcallables = new ArrayList (); for (int i = 0; i < 10; i++) { MyCallable myCallable = new MyCallable(i); callables.add(myCallable); } List > res = executor.invokeAll(callables); for (Future future : res) { System.out.println(future.get()); } } } class MyCallable implements Callable { private int num; public MyCallable(int num) { this.num = num; } @Override public Integer call() throws Exception { System.out.println(Thread.currentThread().getName() + " is running"); return num * 2; } }
多線程框架對象執行定時任務
使用Executor的schedule()函數族來調度線程池中的線程來執行callable執行類對象中的call()定時任務:
public class ThreadTest { public static void main(String[] args) throws InterruptedException, ExecutionException { ScheduledExecutorService executorService = Executors .newScheduledThreadPool(2); MyCallable callable = new MyCallable(2); executorService.schedule(callable, 10, TimeUnit.SECONDS); executorService.shutdown(); } } class MyCallable implements Callable{ private int num; public MyCallable(int num) { this.num = num; } @Override public Integer call() throws Exception { System.out.println(Thread.currentThread().getName() + " is running"); return num * 2; } }
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/64616.html
摘要:線程可以被稱為輕量級進程。一個守護線程是在后臺執行并且不會阻止終止的線程。其他的線程狀態還有,和。上下文切換是多任務操作系統和多線程環境的基本特征。在的線程中并沒有可供任何對象使用的鎖和同步器。 原文:Java Multi-Threading and Concurrency Interview Questions with Answers 翻譯:并發編程網 - 鄭旭東 校對:方騰飛 多...
摘要:多線程和并發問題是技術面試中面試官比較喜歡問的問題之一。線程可以被稱為輕量級進程。一個守護線程是在后臺執行并且不會阻止終止的線程。其他的線程狀態還有,和。上下文切換是多任務操作系統和多線程環境的基本特征。 多線程和并發問題是 Java 技術面試中面試官比較喜歡問的問題之一。在這里,從面試的角度列出了大部分重要的問題,但是你仍然應該牢固的掌握Java多線程基礎知識來對應日后碰到的問題。(...
摘要:整個包,按照功能可以大致劃分如下鎖框架原子類框架同步器框架集合框架執行器框架本系列將按上述順序分析,分析所基于的源碼為。后,根據一系列常見的多線程設計模式,設計了并發包,其中包下提供了一系列基礎的鎖工具,用以對等進行補充增強。 showImg(https://segmentfault.com/img/remote/1460000016012623); 本文首發于一世流云專欄:https...
摘要:大多數待遇豐厚的開發職位都要求開發者精通多線程技術并且有豐富的程序開發調試優化經驗,所以線程相關的問題在面試中經常會被提到。掌握了這些技巧,你就可以輕松應對多線程和并發面試了。進入等待通行準許時,所提供的對象。 最近看到網上流傳著,各種面試經驗及面試題,往往都是一大堆技術題目貼上去,而沒有答案。 不管你是新程序員還是老手,你一定在面試中遇到過有關線程的問題。Java語言一個重要的特點就...
摘要:一使用線程池的好處線程池提供了一種限制和管理資源包括執行一個任務。每個線程池還維護一些基本統計信息,例如已完成任務的數量。通過重復利用已創建的線程降低線程創建和銷毀造成的消耗。使用無界隊列作為線程池的工作隊列會對線程池帶來的影響與相同。 歷史優質文章推薦: Java并發編程指南專欄 分布式系統的經典基礎理論 可能是最漂亮的Spring事務管理詳解 面試中關于Java虛擬機(jvm)的問...
閱讀 1117·2021-11-25 09:43
閱讀 1639·2021-09-13 10:25
閱讀 2592·2021-09-09 11:38
閱讀 3400·2021-09-07 10:14
閱讀 1714·2019-08-30 15:52
閱讀 641·2019-08-30 15:44
閱讀 3572·2019-08-29 13:23
閱讀 1974·2019-08-26 13:33