2016-06-19 3 views
2

私はリファクタリングできないレガシーコードを作成しています。isDoneでポーリングを使用し、キャンセルするのではなくJava Futureでキャンセルする

このコードでは、Java Futureのブロックを使用しています。これはfuture.get(withTimeOut、...)を使用します。これは、適切なサイズのスレッドプールを十分に応答させる必要があることを意味します。コールが終了するか、タイムアウトするまでブロックされます。

質問: 私は未来をつかんで、それをタスクの実行の開始を認識するデータ構造に入れようと考えていました。次に、専用のスレッドまたはプールを用意して、データ構造をループし、future.isDoneまたはタイムアウトの制限を超えているかどうかを確認します。はいの場合、結果を取得するか、実行を取り消すことができます。この方法では、多くのスレッドが必要ではありません。正しい実装か、まったくお勧めできませんか?

ありがとうございます。

編集:

ただ、多くのコンテキストを提供します。これらのスレッドは、ダウンストリームサービスへのロギングに使用されます。私たちは実際に応答に気にしませんが、接続が掛かっていることを望んでいません。したがって、未来をつかみ、それがキャンセルされるかタイムアウトすることを確実にする必要があります。

ここに質問をした後に書いた基本的なシミュレーションです。

@Component 
public class PollingService { 

    private ExecutorService executorService = Executors.newFixedThreadPool(1); 
    PoorMultiplexer poorMultiplexer = new PoorMultiplexer(); 
    private ConcurrentMap<Integer, Map<Future, Long>> futures = new ConcurrentHashMap<>(); 

    public void startHandler(){ 
     Thread handler = new Thread(new Runnable() { 
      @Override 
      public void run() { 
       while(true){ 
        try { 
         //This should be handled better. If there is not anything stop and re-start it later. 
         Thread.sleep(200); 
        } catch (InterruptedException e) { 
         e.printStackTrace(); 
        } 
        for(Iterator<ConcurrentMap.Entry<Integer, Map<Future, Long>>> it = futures.entrySet().iterator(); it.hasNext();){ 
         ConcurrentMap.Entry<Integer, Map<Future, Long>> entry = it.next(); 
         Map<Future, Long> futureMap = entry.getValue(); 
         boolean isProcessed = false; 
         if(futureMap.keySet().iterator().next().isDone()){ 
          //mark completed 
          isProcessed = true; 
         } 

         if(futureMap.values().iterator().next() < (300 + System.currentTimeMillis()) && !isProcessed){ 
          //cancel 
          futureMap.keySet().iterator().next().cancel(true); 
          isProcessed = true; 
         } 

         if(isProcessed){ 
          futures.remove(entry.getKey()); 
          System.out.println("Completed : " + entry.getKey()); 
         } 

        } 

        System.out.println("Run completed"); 
       } 
      } 
     }); 

     handler.start(); 
    } 

    public void run(int i) throws InterruptedException, ExecutionException{ 
     System.out.println("Starting : " + i); 

     poorMultiplexer.send(new Runnable() { 
      @Override 
      public void run() { 
       long startTime = System.currentTimeMillis(); 
       Future future = poorMultiplexer.send(execute()); 

       Map<Future, Long> entry = new HashMap<>(); 
       entry.put(future, startTime); 
       futures.put(i, entry); 
       System.out.println("Added : " + i); 
      } 
     }); 
    } 

    public void stop(){ 
     executorService.shutdown(); 
    } 

    public Runnable execute(){ 
     Worker worker = new Worker(); 
     return worker; 
    } 
} 


//This is a placeholder for a framework 
class PoorMultiplexer { 
    private ExecutorService executorService = Executors.newFixedThreadPool(20); 

    public Future send(Runnable task){ 
     return executorService.submit(task); 
    } 
} 


class Worker implements Runnable{ 

    @Override 
    public void run() { 
     //service call here 
    } 

} 
+0

あなたの質問は広すぎると思います。設計の助けを求めるとき、答えは一般的に「意見」です。どのような解決策にも長所と短所があります。本当に正確です。あなたの実装が**正しい**かどうかは言えません。 10000フィートからあなたのアイデアの上に合理的な音;しかし、もう一度:私たちは詳細はあまりありません。ちょっとしたUMLをスケッチした方がいいかもしれません...そして、アプリケーションを知っている相手に話して、彼らの意見を聞いてください。どのような変更が理にかなっているかについて実際にコードを知らない他の人に尋ねると、単に素晴らしいアンサーになることはできません。 – GhostCat

+0

@Jägermeister私は、通話をブロックすることが一般的な問題だと感じています。私はここで質問した後にサンプルを実装しましたが、動作するようですが、それ以上の処理が必要です。あなたは正しいです、私はより多くの情報を提供していたはずです。 –

答えて

1

個別のスレッドを使用して未処理の一連のFuturesを非公式にポーリングすることは、私にとって妥当な実装のように聞こえます。つまり、ライブラリの依存関係を追加することができれば、Guavaは非同期作業を行うための豊富なユーティリティを提供しているため、GuavaのListenableFutureに簡単に切り替えることができます。

+0

はい、これらのことはほとんど読んでいませんが、残念ながら追加するのは難しいでしょう。お返事をありがとうございます。 –

関連する問題