Java JDK1.8(21) - 多線程併發設計模式 - Future設計模式、Master-Worker設計模式

Future模式

/**

 * Future模式:是並行模式屬於設計優化的一部分,是對一些常用的多線程結構的總結和抽象。

 * 與串行程序相比,並行程序的結構通常更爲複雜,因此合理的使用並行模式在多線程開發中更具有意義。

 * 這個模式類似在發送ajax請求,頁面是異步的進行後臺處理,用戶無須一直等待結構就可以繼續瀏覽和進行其他操作。

 */

public class C03Future {

    public static void main(String[] args) throws InterruptedException {

         Client client = new Client();

         String data = client.getData("123");

         System.out.println(data);

    }

}

class Client {

   

    public String getData(String query) throws InterruptedException {

         //獲取到代理對象

         ProxyData proxyData = new ProxyData();

        

         //偷偷起個線程去加載數據

         new Thread(new Runnable() {

             @Override

             public void run() {

                  System.out.println("開始加載數據");

                  HandlerData handlerData = null;

                  try {

                      handlerData = new HandlerData(query);

                     

                      //設置加載好的數據給代理對象

                      System.out.println("數據加載完成");

                      proxyData.setHandlerData(handlerData);

                  } catch (InterruptedException e) {

                      e.printStackTrace();

                  }

             }

         }).start();

        

         System.out.println("返回代理對象");

        

         return proxyData.getHandlerData();

    }

   

}

/**

 * 數據代理

 */

class ProxyData {

   

    private HandlerData handlerData;

   

    private boolean isReady = false;

   

    /**

     * 設置數據,如果數據已有就直接返回,沒有數據就進行處理。

     * 假設:數據處理過程需要耗時N秒,用戶在get時,就節省了部分過程的時間。

     */

    public synchronized void setHandlerData(HandlerData handlerData) {

         //數據已經準備好了,直接返回

         if (isReady) {

             System.out.println(isReady + ":數據未準備好");

             return ;

         }

         //數據沒有準備好,開始進行數據處理

         this.handlerData = handlerData;

         isReady = true;

        

         System.out.println("代理對象設置數據成功,喚醒getHandlerData的等待。");

         //喚醒通知

         notify();

    }

   

    /**

     * 獲取數據

     */

    public synchronized String getHandlerData() throws InterruptedException {

         //如果數據沒有處理好,則等待處理

         while (!isReady) {

             System.out.println(isReady + ":數據未準備好,getHandlerData 進入等待");

             wait();

         }

        

         //返回裝好的數據

         return this.handlerData.getResult();

    }

}

/**

 * 真實的數據

 */

class HandlerData {

    /**

     * 數據結果

     */

    private String result;

   

    /**

     * 模擬數據處理過程

     */

    public HandlerData(String query) throws InterruptedException {

         System.out.println("模擬-數據查詢");

        

         //數據處理

         Thread.sleep(5000);

        

         System.out.println("模擬-數據處理完成");

         result = "end";

    }

 

    public String getResult() {

         return result;

    }

}

public class C03Future01 {

    public static void main(String[] args) throws InterruptedException, ExecutionException {

        

         //JDK自帶Api ==========================================

         String query = "select * from user;";

        

         //構建FutureTask,並且傳入需要真正進行業務處理和實現了Callable接口的類

         FutureTask<String> futureTask1 = new FutureTask<String>(new FutureTestClass(query));

         FutureTask<String> futureTask2 = new FutureTask<String>(new FutureTestClass(query));

        

         //創建一個固定線程的線程池

         ExecutorService pool = Executors.newFixedThreadPool(1);

        

         //提交任務,則開啓線程執行call方法

         //submit()execute()方法的區別,可以看線程池篇的文章

         Future submit1 = pool.submit(futureTask1);

         Future submit2 = pool.submit(futureTask2);

        

         System.out.println("Main線程處理別的業務邏輯");

         Thread.sleep(2000);

        

         System.out.println(futureTask1.get());

         System.out.println(futureTask2.get());

        

         pool.shutdown();

    }

}

/**

 * 必須要實現Callable接口

 */

class FutureTestClass implements Callable<String> {

   

    private String query;

 

    public FutureTestClass(String query) {

         super();

         this.query = query;

    }

 

    @Override

    public String call() throws Exception {

         Thread.sleep(3000);

         String result = query + ":處理完成";

         return result;

    }

}

 


Master-Worker模式

/**

 * Master-Wroker模式:這也是常用的並行模式,核心思想是系統由MasterWorker兩類進行協同工作。

 * Master負責接收和分配任務,Worker負責處理子任務,但各個Worker子進程處理完成後,會將結果返回給Master,由Master歸納和總結。

 * 好處就是能將一個大任務分解成爲若干個小任務並行執行,從而提高系統的吞吐量。

 * 現有框架設計:HadoopSpark

 */

public class C04MasterWorker {

    public static void main(String[] args) {

        

         //設置NWorker同時執行

         Master master = new Master(100);

        

         //提交100個任務給master

         for (int i = 0; i < 100; i++) {

             master.submitTask(new Task(i,i + " " + "Test"));

         }

        

         //開始執行

         master.execute();

        

         long startTime = System.currentTimeMillis();

        

         while (true) {

             if(master.isComplete()) {

                  long endTime = System.currentTimeMillis();

                  System.out.println("結果:" + master.getResult().size());

                  System.out.println("運行時間:" + (endTime - startTime));

                  break;

             }

         }

        

         /*

          * 1Master在初始化時,就生成好對應數量的Worker了,並放在容器中。

          * 1.1Worker會有MasterTask併發存儲容器的引用和併發結果容器存放的引用,讓Worker可以獲取到任務和存放執行結果。

          * 2、在提交Task時,由於Worker是併發執行的,所以每一個Task也是存放在併發容器中的。

          * 3、調用Master執行方法時,則取出Worker容器中的每一個Worker,啓動該線程去執行任務。

          * 3.1、每一個Worker線程會取出MasterTask併發存儲容器中的Task去執行,執行完一個則取出下一個,取的方法是取出後在容器刪除這個Task,避免重複執行。

          */

        

    }

}

/**

 * 負責接收和分配任務,並收集所有Worker處理的結果

 */

class Master {

   

    //存放任務容器

    private ConcurrentLinkedQueue<Task> workerTasks = new ConcurrentLinkedQueue<>();

   

    //存放執行的Worker(併發執行)

    private Map<String, Thread> workers = new HashMap<>();

   

    //存放Worker執行結果(併發執行)

    private ConcurrentHashMap<String, Object> result = new ConcurrentHashMap<>();

 

    /**

     * 初始化Master時,也初始化出對應數量的Worker

     * @param worker Worker

     * @param workerCount

     */

    public Master(int workerCount) {

         //將容器引用設置過去給Worker

         Worker worker = new Worker();

         worker.setWorkerTasks(workerTasks);

         worker.setResult(result);

        

         for (int i = 0; i < workerCount; i++) {

             this.workers.put(i + "", new Thread(worker));

         }

    }

   

    /**

     * 初始化完成對應的Worker之後,要能讓用戶提交Task,在將Task分配給對應的Worker去執行

     * @param task

     * @return boolean

     */

    public boolean submitTask(Task task) {

         return this.workerTasks.add(task);

    }

   

    /**

     * 提交完成任務後,要讓Workers去執行任務

     * @return boolean

     */

    public boolean execute() {

         for (Entry<String, Thread> entry : workers.entrySet()) {

             entry.getValue().start();

         }

         return true;

    }

   

    /**

     * 所有任務是否已經運行完成

     * @return boolean

     */

    public boolean isComplete() {

         for (Entry<String, Thread> entry : workers.entrySet()) {

             if (entry.getValue().getState() != Thread.State.TERMINATED) {

                  return false;

             }

         }

         return true;

    }

   

    /**

     * 獲取到執行結果

     * @return List<Object>

     */

    public List<Object> getResult() {

         List<Object> result = new ArrayList<>();

         for (Entry<String, Object> entry : this.result.entrySet()) {

             result.add(entry.getValue());

         }

         return result;

    }

   

}

/**

 * 具體處理任務

 */

class Worker implements Runnable {

   

    //Master分配過來,要執行的任務

    private ConcurrentLinkedQueue<Task> workerTasks;

   

    //執行的結果

    private ConcurrentHashMap<String, Object> result;

 

    public void setWorkerTasks(ConcurrentLinkedQueue<Task> workerTasks) {

         this.workerTasks = workerTasks;

    }

 

    public void setResult(ConcurrentHashMap<String, Object> result) {

         this.result = result;

    }

 

    /*

     * 多線程執行分配到的任務

     */

    @Override

    public void run() {

         while (true) {

             Task task = this.workerTasks.poll();

             if (null == task) {

                  break;

             }

             //任務處理,並把處理結果放到容器中

             Object handleResult = handle(task);

             this.result.put(task.getId().toString(), handleResult);

         }

    }

   

    /**

     * 模擬任務處理邏輯

     */

    private Object handle(Task task) {

         try {

             Thread.sleep(300);

         } catch (InterruptedException e) {

             e.printStackTrace();

         }

         String desc = task.getDesc();

         return desc;

    }

   

}

/**

 * 任務

 */

class Task {

   

    private Integer id;

   

    private String desc;

 

    public Task(Integer id, String desc) {

         super();

         this.id = id;

         this.desc = desc;

    }

 

    public Integer getId() {

         return id;

    }

 

    public void setId(Integer id) {

         this.id = id;

    }

 

    public String getDesc() {

         return desc;

    }

 

    public void setDesc(String desc) {

         this.desc = desc;

    }

}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章