一歩一歩java同時プログラミングモードのActive Objectモード(三)java実現active object


今、active objectモードの核心思想を知っていて、どのように自分で類似の効果を実現するjavaコードを書くかも分かりました.ここではactive objectモードの役割分担に従い,第2編の例を再実現し,JavaにおけるActive Object同時モードの応用というブログを参照した.Active Objectモードでは、主に次のタイプの参加者がいます.
  • エージェント(proxy):エージェントはActive Objectによって定義された呼び出し元に対する共通インタフェースである.実行時、エージェントは呼び出しスレッドのコンテキストで実行され、呼び出し者のメソッド呼び出しを対応するメソッド要求(Method Request)に変換し、対応するActivation Listに挿入し、最後に呼び出し者Futureオブジェクトに返す.エージェントロールには、
  • という特徴があります.
            1.Proxyとservantは同じインタフェース署名を持っているか、proxyはservantインタフェースよりも簡単で使いやすい.これにより、呼び出し者がproxyとservantに無差別に対処したり、エージェント2をより容易に使用することができる.クライアントに必要なfutureオブジェクトを作成し、呼び出しスレッドが長時間待つことを避けるために迅速に戻ります.クライアントは、futureオブジェクトから実際の演算結果3を取得することができる.呼び出し元のメソッド呼び出しを対応するメソッド要求(Method Request)に変換し、requestとservantをschedulerに渡してスケジューリング実行する.エージェントは呼び出し者スレッドで実行され、元の時間消費サービスをカプセル化し、クライアントがエージェントと実際のオブジェクトを差別なく使用できるようにした.
  • メソッド要求(method request):メソッド要求は、呼び出しパラメータなどのメソッド実行に必要なコンテキスト情報を定義する.
  • activation list:エージェントによって作成され、実行を待つすべてのメソッド要求を格納します.実行時から見ると、Activation Listは呼び出し元スレッドとそのActive Objectスレッドとを含む同時アクセスアクセスアクセスによってアクセスされるので、Activation List実装はスレッドが安全であるべきである.
  • スケジューラ(scheduler):スケジューラはActive Objectスレッドで実行され、スケジューラは次の実行方法要求を決定し、スケジューラポリシーは、方法要求によって挿入された順序FIFOまたはLIFO、例えば方法によって求められる優先度など、多くの基準に基づいてもよい.
  • servant::サーバントは、Proxyが定義したインタフェースの事実上の実装であるActive Objectの動作と状態を定義します.
  • future:呼び出し元はProxyで定義されたメソッドを呼び出し、Futureオブジェクトを取得します.呼び出し元は、このFutureオブジェクトからメソッド実行の最終結果を得ることができる.実際のインプリメンテーションでは、Futureオブジェクトは、サーバントメソッドの実行結果を格納するためにプライベートなスペースを保持します.

  • 次にservantクラスを作成します.これはactive objectロール全体で最も簡単です.
    package activeobject.aty.servant;
    
    import activeobject.aty.result.WeatherResult;
    
    //Servant              ,          ,              ,                ,               。
    public class WeatherServant
    {
        public WeatherResult getWeatherInfo(String city, String day)
        {
            try
            {
                //       ,        ,   5s
                Thread.sleep(5 * 1000);
            }
            catch (InterruptedException e)
            {
    
            }
    
            WeatherResult result = new WeatherResult();
            result.setTemperature(28);
            result.setWindDirection("   ");
            result.setDampness("74%");
    
            return result;
        }
    
    }
    package activeobject.aty.result;
    
    //            
    //      :  :4℃;  /  :    1 ;  :74%;    : ;     :  
    public class WeatherResult
    {
     //   
     private int temperature;
    
     //   
     private String dampness;
    
     //   
     private String windDirection;
    
     public int getTemperature()
     {
         return temperature;
     }
    
     public void setTemperature(int temperature)
     {
         this.temperature = temperature;
     }
    
     public String getDampness()
     {
         return dampness;
     }
    
     public void setDampness(String dampness)
     {
         this.dampness = dampness;
     }
    
     public String getWindDirection()
     {
         return windDirection;
     }
    
     public void setWindDirection(String windDirection)
     {
         this.windDirection = windDirection;
     }
    
     @Override
     public String toString()
     {
         return "WeatherResult [temperature=" + temperature + ", dampness=" + dampness + ", windDirection="
                 + windDirection + "]";
     }
     
    
    
    }

    methodrequestとfutureコードを作成します
    package activeobject.aty.future;
    
    import activeobject.aty.result.WeatherResult;
    
    //       Proxy       ,   Futur   。        Future              。
    //        ,Future             ,     Servant        。
    public class WeatherFuture
    {
        private boolean isDone = false;
    
        private WeatherResult result = null;
    
        public WeatherResult get()
        {
            while (!isDone)
            {
    
            }
    
            return result;
        }
    
        public void setDone(boolean isDone)
        {
            this.isDone = isDone;
        }
    
        public void setResult(WeatherResult result)
        {
            this.result = result;
        }
    
    }
    package activeobject.aty.methodrequest;
    
    import activeobject.aty.future.WeatherFuture;
    import activeobject.aty.result.WeatherResult;
    import activeobject.aty.servant.WeatherServant;
    
    // Method Request:                    ,      、           
    public class WeatherMethodRequest
    {
        private WeatherFuture future;
    
        private WeatherServant servant;
    
        private String city;
    
        private String day;
    
        public WeatherMethodRequest(WeatherFuture future, WeatherServant servant, String city, String day)
        {
            this.future = future;
            this.servant = servant;
            this.city = city;
            this.day = day;
        }
    
        public void call()
        {
            WeatherResult result = servant.getWeatherInfo(city, day);
    
            future.setResult(result);
            future.setDone(true);
        }
    
    }

    次にactivationリストを作成します
    package activeobject.aty.activationlist;
    
    import java.util.ArrayList;
    import java.util.List;
    
    import activeobject.aty.methodrequest.WeatherMethodRequest;
    
    // Activation List             ,         。
    //       ,Activation List             Active Object        ,  Activation List           .
    
    // Activation List                    Method Request  ,          (insert/remove)         。
    //      ,Activation List              /          ,           
    // Method Request     ,Active Object               Method Request,    。
    public class WeatherActivationList
    {
        private List<WeatherMethodRequest> requestList = new ArrayList<WeatherMethodRequest>();
    
        public synchronized void insertTask(WeatherMethodRequest request)
        {
            requestList.add(request);
        }
    
        public synchronized void removeTask(WeatherMethodRequest request)
        {
            requestList.remove(request);
        }
    
        public synchronized boolean isEmpty()
        {
            return requestList.size() == 0;
        }
    
        public synchronized WeatherMethodRequest popFirst()
        {
            WeatherMethodRequest e = requestList.get(0);
    
            requestList.remove(0);
    
            return e;
        }
    }

    ここまでのリクエストはactivatio listにあり、activation listに基づいてscheduler実装を記述することができます.
    package activeobject.aty.scheduler;
    
    import activeobject.aty.activationlist.WeatherActivationList;
    import activeobject.aty.methodrequest.WeatherMethodRequest;
    
    // Active Object    
    public class WeatherStartThread implements Runnable
    {
        private WeatherActivationList safeRequestList;
    
        public WeatherStartThread(WeatherActivationList safeRequestList)
        {
            this.safeRequestList = safeRequestList;
        }
    
        @Override
        public void run()
        {
            while (true)
            {
                if (!safeRequestList.isEmpty())
                {
                    WeatherMethodRequest request = safeRequestList.popFirst();
                    request.call();
                }
            }
        }
    
    }
    package activeobject.aty.scheduler;
    
    import activeobject.aty.activationlist.WeatherActivationList;
    import activeobject.aty.methodrequest.WeatherMethodRequest;
    
    // scheduler:       Active Object   ,                ,
    //               ,               FIFO    LIFO,              。
    public class WeatherTaskScheduler
    {
        private WeatherActivationList safeRequestList = new WeatherActivationList();
    
        public WeatherTaskScheduler()
        {
            new Thread(new WeatherStartThread(safeRequestList)).start();
        }
    
        public void insertRequest(WeatherMethodRequest methodRequest)
        {
            safeRequestList.insertTask(methodRequest);
        }
    
    
    }

    次に、クライアントが直接使用するクラスであるエージェントクラスの実装について説明します.
    package activeobject.aty.proxy;
    
    import activeobject.aty.future.WeatherFuture;
    import activeobject.aty.methodrequest.WeatherMethodRequest;
    import activeobject.aty.scheduler.WeatherTaskScheduler;
    import activeobject.aty.servant.WeatherServant;
    
    //   (Proxy)      :
    // 1.proxy servant         ,  proxy servant       。               proxy servant,         
    // 2.  client   future  ,     ,            .       future           
    // 3.                    (Method Request), request servant  scheduler      
    // 4.             ,              ,                 ,    .
    public class WeatherProxy
    {
        //        
        private static WeatherTaskScheduler scheduler = new WeatherTaskScheduler();
    
        //        
        private static WeatherServant servant = new WeatherServant();
    
        public static WeatherFuture getWeatherInfo(String city, String day)
        {
            WeatherFuture futureResult = new WeatherFuture();
    
            WeatherMethodRequest request = new WeatherMethodRequest(futureResult, servant, city, day);
    
            scheduler.insertRequest(request);
    
            return futureResult;
        }
    }

    最後に、テストクラスを作成して、私たちの機能を検証します.
    package activeobject.aty;
    
    import activeobject.aty.future.WeatherFuture;
    import activeobject.aty.proxy.WeatherProxy;
    import activeobject.aty.result.WeatherResult;
    
    public class TestWeather {
    
    	public static void main(String[] args) throws Exception {
    		mockMultiCall();
    
    		testAsyncCall();
    	}
    
    	public static void testAsyncCall() throws Exception {
    		// 1.        ,           (    )
    		WeatherFuture future = WeatherProxy
    				.getWeatherInfo("    ", "2014-03-14");
    
    		// 2.          .        ,        .
    		System.out.println("After calling weather service,i am still running.");
    
    		// 3.The current thread is not blocked, do something else here...
    		// Thread.sleep(5 * 1000);
    
    		// 4.                .
    		System.out.println("Now,i really need weather result to continue.");
    
    		// 5.           ,        ,      .
    		WeatherResult info = future.get();
    		System.out.println("      :" + info);
    	}
    
    	public static void mockMultiCall() {
    		Thread t = new Thread(new Runnable() {
    			@Override
    			public void run() {
    				while (true) {
    					long time = System.currentTimeMillis();
    
    					System.out.println("          :");
    					WeatherFuture future = WeatherProxy.getWeatherInfo("    "
    							+ time, "2014-03-14");
    					WeatherResult info = future.get();
    					System.out.println("mockMultiCall  :" + info);
    					System.out.println();
    					System.out.println();
    				}
    			}
    		});
    
    		t.start();
    	}
    }

    これにより,active objectモードの各参加者および職責に従ってjava実装を完了した.