【デザインパターン】【非同期】 Future パターン

 ■ Future パターン

* 将来実行できる状態になるまで待つ
* 処理の実行担当者は、処理が渡されると別スレッド上で処理を開始して、
 メインスレッドには即座にFutureオブジェクトを返すこと
* 現在はまだ結果を取得できないが、将来のある時点で取得することになる

補足:JavaScript/TypeScriptの場合

* JavaScript/TypeScriptの場合、Promiseオブジェクトに当たる。

非同期処理 ~ async/await, Promise ~
https://dk521123.hatenablog.com/entry/2021/01/16/202822

 ■ サンプル

http://www.hyuki.com/dp/dpinfo.html#Future

を参考に、Future パターンを理解するためのプログラムを組む。
(実際には、java.util.concurrent を使った方がいいらしいので、あくまで理解のため)

 IDrawing.java

// インターフェイスを用意する 
public interface IDrawing {
   public abstract void draw(String content);
}

 FutureDrawer.java

// 用意したインターフェイスを継承する 
public class FutureDrawer implements IDrawing {
   private IDrawing drawer;

   public synchronized void draw(String content) {
      while (this.drawer == null) {
         try {
            System.out.println("\tIn FutureDrawer: wait");
            wait();
         } catch (InterruptedException e) {
         }
      }
      System.out.println("\tIn FutureDrawer : drawing start.");
      this.drawer.draw(content);
   }

   public synchronized void setPrinter(IDrawing drawer) {
      this.drawer = drawer;
      notifyAll();
   }
}

 RealDrawer.java

// 用意したインターフェイスをこっちも継承する 
public class RealDrawer implements IDrawing {
    public void draw(String content) {
        System.out.println("\tRealDrawer draws \"" + content + "\"");
    }
}

 DrawManager.java

import java.util.Random;

public class DrawManager extends Thread {
   private FutureDrawer drawer;

   public DrawManager() {
      this.drawer = new FutureDrawer();
   }

   public void run() {
      System.out.println(Thread.currentThread().getName() + " is sleeping.");
      try {
         this.doHeavyJob();
      } catch (InterruptedException e) {
      }
      System.out.println(Thread.currentThread().getName()
            + " sets a RealDrawera.");
      this.drawer.setPrinter(new RealDrawer());
   }

   public void requestDrawing(String content) {
      this.drawer.draw(content);
   }

   private void doHeavyJob() throws InterruptedException {
      Random random = new Random();
      Thread.sleep(random.nextInt(10000));
   }
}

 Main.java

public class Main {
    public static void main(String[] args) {
       DrawManager drawManager = new DrawManager();
       drawManager.start();
        
       System.out.println(
              Thread.currentThread().getName() + " is drawing...");
        
       drawManager.requestDrawing("Hello Mike  [1].");
       drawManager.requestDrawing("Hello Tom   [2].");
       drawManager.requestDrawing("Hello World [3].");
    }
}

 出力

Thread-0 is sleeping.
main is drawing...
    In FutureDrawer: wait
Thread-0 sets a RealDrawera.
    In FutureDrawer : drawing start.
    RealDrawer draws "Hello Mike  [1]."
    In FutureDrawer : drawing start.
    RealDrawer draws "Hello Tom   [2]."
    In FutureDrawer : drawing start.
    RealDrawer draws "Hello World [3]."

 ■ 補足

 * Future インターフェースがJava標準で用意されている

http://www.techscore.com/tech/Java/JavaSE/Thread/8-3/

 参考文献

http://www.hyuki.com/dp/dpinfo.html#Future
http://team-pag.interprism.co.jp/member/okazawa/blog/?p=704

関連記事

非同期処理 ~ async/await, Promise ~
https://dk521123.hatenablog.com/entry/2021/01/16/202822
Python ~ 非同期 / concurrent.futures ~
https://dk521123.hatenablog.com/entry/2023/04/19/232949
Scala ~ 非同期 / Future ~
https://dk521123.hatenablog.com/entry/2023/04/30/000000