標籤:lov 抽象 啟動 cep 異常 步驟 over task submit
線程池和lambda運算式
學習線程池和lambda運算式的理解
補充一個知識點(單例設計模式)
在多線程中,我們只需要一個任務類,為了防止建立多個任務類,這個時候就需要用到單例模式,單例模式有兩種設計:
- 消極式載入(懶漢式)
- 私人構造方法
- 建立本類對象,但不初始化
- 建立靜態方法進行初始化對象並返回
- 立即載入(餓漢式)
- 私人構造方法
- 建立本類的對象並初始化(私人的)
- 建立靜態方法擷取本類對象
下面用代碼做個執行個體:
package com.wzlove.single;/** * 消極式載入(懶漢式) * 1.私人構造方法 * 2.建立本類對象,但不初始化 * 3.建立靜態方法進行初始化對象並返回 * * 優點: * 使用到類的對象才會載入,不消耗記憶體 * 缺點: * 可能會出現安全執行緒問題,但是可以使用同步代碼塊消除這個安全問題 * @author WZLOVE * @create 2018-07-19 10:36 */public class DeplayedSingle { // 私人構造方法 private DeplayedSingle(){} // 建立本類對象,不初始化 private static DeplayedSingle instance ; // 靜態方法初始化 public static DeplayedSingle getInstance(){ synchronized (DeplayedSingle.class){ if(instance == null){ instance = new DeplayedSingle(); } } return instance; }}package com.wzlove.single;/** * 立即載入(餓漢式) * 1.私人構造方法 * 2.建立本類的對象並初始化(私人的) * 3.建立靜態方法擷取本類對象 * * 優點: * 保證的線程的安全,沒有安全執行緒問題 * 缺點: * 使用類就會載入,比較消耗記憶體 * @author WZLOVE * @create 2018-07-19 10:37 */public class ImmediateSingle { private ImmediateSingle(){} private static ImmediateSingle instance = new ImmediateSingle(); public static ImmediateSingle getInstance(){ return instance; }}
線程池概述
線程池其實就是一個容納多個線程的容器,其中的線程可以反覆使用,省去了頻繁建立線程對象的操作,
無需反覆建立線程而消耗過多資源。作用是節省資源,原理是容器.
使用線程池的好處是減少在建立和銷毀線程上所花的時間以及系統資源的開銷,解決資源不足的問題.如果不使用線程池,
有可能造成系統建立大量同類線程而導致消耗完記憶體或者"過度切換"的問題.
建立線程池:
- public static ExecutorService newFixedThreadPool(int nThreads) :返回線程池對象。(建立的是有界線
程池,也就是池中的線程個數可以指定最大數量)
- public Future<?> submit(Runnable task) :擷取線程池中的某一個線程對象,並執行
- Future介面:用來記錄線程任務執行完畢後產生的結果。線程池建立與使用。
步驟:
- 使用線程池的工廠類Executors裡面提供靜態方法newFixedThreadPool生產一個指定線程數量的線程池
- 建立一個類,實現Runnable介面,重寫run方法,設定線程任務
- 調用ExecutorService中的方法submit,傳遞線程任務(實作類別),開啟線程(前提是線程池中有線程可用),執行run方法
- 調用ExecutorService中的shutdown方法銷毀線程池(不建議執行)
補充線程的建立
建立線程的第三種方式(這種方式很少見)
package com.wzlove.executor;import java.util.ArrayList;import java.util.concurrent.Callable;/** * 線程的第三種建立方法 * Callable有傳回值並且可以拋出異常 * @author WZLOVE * @create 2018-07-18 14:14 */public class CallableImpl implements Callable<String> { private static ArrayList<String> arrayList = new ArrayList<>(); static{ arrayList.add("1"); } @Override public String call() throws Exception { return Thread.currentThread().getName(); }}package com.wzlove.executor;import java.util.concurrent.*;/** * 測試線程的第三中建立方式 * * @author WZLOVE * @create 2018-07-18 14:14 */public class Demo { public static void main(String[] args) { // 建立實現Callable的實作類別對象 Callable<String> callable = new CallableImpl(); // 建立FutureTask,並傳遞Callable介面的實作類別對象 FutureTask task = new FutureTask(callable); // 建立線程池對象 // ExecutorService executor = Executors.newSingleThreadExecutor(); ExecutorService executor = Executors.newFixedThreadPool(3); executor.submit(callable); // 執行線程 executor.execute(task); try { System.out.println(task.get()); } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } }}
Lambda運算式
lambda體現的是一種函數式編程的思想, 它強調的是做什麼,而不是以什麼形式做。
使用前提
- 使用Lambda必須具有介面,且要求介面中有且僅有一個抽象方法。無論是JDK內建的Runnable 、Comparator 介面還是自訂的介面,只有當介面中的抽象方法存在且唯一時,才可以使用Lambda。
- 使用Lambda必須具有上下文推斷。也就是方法的參數或局部變數類型必須為Lambda對應的介面類型,才能使用Lambda作為該介面的執行個體。
有且僅有一個抽象方法的介面,稱為“函數式介面”。
Lambda標準格式
Lambda省去物件導向的條條框框,格式由3個部分組成:
Lambda運算式的標準格式為:
(參數類型 參數名稱) ‐> { 代碼語句 }
格式說明:
- 小括弧內的文法與傳統方法參數列表一致:無參數則留空;多個參數則用逗號分隔。
- -> 是新引入的文法格式,代表指向動作。
- 大括弧內的文法與傳統方法體要求基本一致。
線程匿名內部類的轉化(無參無傳回值)
實現Runnable介面的匿名內部類的實現:
public class Demo01Runnable { public static void main(String[] args) { // 匿名內部類 Runnable task = new Runnable() { @Override public void run() { // 覆蓋重寫抽象方法 System.out.println("多線程任務執行!"); } }; new Thread(task).start(); // 啟動線程 }}
程式碼分析
- Thread 類需要Runnable 介面作為參數,其中的抽象run 方法是用來指定線程任務內容的核心;
- 為了指定run 的方法體,不得不需要Runnable 介面的實作類別;
- 為了省去定義一個RunnableImpl 實作類別的麻煩,不得不使用匿名內部類;
- 必須覆蓋重寫抽象run 方法,所以方法名稱、方法參數、方法傳回值不得不再寫一遍,且不能寫錯;
- 而實際上,似乎只有方法體才是關鍵所在。
使用Lambda進行簡化:
public class Demo01Runnable { public static void main(String[] args) { new Thread(()->System.out.println("多線程任務執行!")).start(); // 啟動線程 }}
比較子內部類的轉化(有參有傳回值)
使用比較子舉個例子:
// 建立數組Integer[] arr = {1,8,3,4,9,2,5};// 匿名內部類實現數組升序排序Arrays.sort(arr,new Comparator<Integer>(){ @Override public int compare(Integer o1, Integer o2) { return 0; }});// 使用lambda進行數組的升序排序Arrays.sort(arr,( a, b)->{ return a - b ;});
Lambda運算式的省略規則
在Lambda標準格式的基礎上,使用省略寫法的規則為:
- 小括弧內參數的類型可以省略;
- 如果小括弧內有且僅有一個參,則小括弧可以省略;
- 如果大括弧內有且僅有一個語句,則無論是否有傳回值,都可以省略大括弧、return關鍵字及語句分號。
雖然有省略寫法,但是我感覺這個有點靈活,所以不建議省略,因為代碼是給別人看的,省略的話感覺別人看起來會有點費勁.
Java之線程池和Lambda運算式