學習線程池和lambda表達式的理解java
在多線程中,咱們只須要一個任務類,爲了防止建立多個任務類,這個時候就須要用到單例模式,單例模式有兩種設計:編程
下面用代碼作個實例:設計模式
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; } }
線程池其實就是一個容納多個線程的容器,其中的線程能夠反覆使用,省去了頻繁建立線程對象的操做,
無需反覆建立線程而消耗過多資源。做用是節省資源,原理是容器.數組
使用線程池的好處是減小在建立和銷燬線程上所花的時間以及系統資源的開銷,解決資源不足的問題.若是不使用線程池,
有可能形成系統建立大量同類線程而致使消耗完內存或者"過分切換"的問題.安全
建立線程池:多線程
步驟:ide
建立線程的第三種方式(這種方式不多見)函數式編程
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省去面向對象的條條框框,格式由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標準格式的基礎上,使用省略寫法的規則爲:
雖然有省略寫法,可是我感受這個有點靈活,因此不建議省略,由於代碼是給別人看的,省略的話感受別人看起來會有點費勁.