以异步方式运行方法并能够查看其状态的最简单方法是什么?

时间:2015-12-10 18:37:51

标签: java concurrency gpars

我想运行一个持久的操作,并能够看到它的以下阶段:

1)尚未运行

2)跑步

3)说完了

4)完成异常

我写了下面的代码,看起来过于复杂。它使用三个类:WorkThreadPoolExecutorFutureTask<?>,其中Work是手写的。

同时,工作部分重复FutureTask<?>功能(异常存储,也在Future中完成,但在内部关闭)。

问题是:有没有几种方法可以从Java,Groovy,GPars,Apache等预定义类中做同样的事情?

代码:

public class AsyncRunAndTrackState {

   public static class Stub implements Runnable {
      @Override
      public void run() {
         try {
            Thread.sleep(1000);
         } catch (InterruptedException e) {
            e.printStackTrace();
         }
      }
   }

   public static class Work implements Runnable {

      private Exception exception;

      private boolean active;

      public synchronized Exception getException() {
         return exception;
      }

      public synchronized void setException(Exception exception) {
         this.exception = exception;
      }

      public synchronized boolean isActive() {
         return active;
      }

      public synchronized void setActive(boolean active) {
         this.active = active;
      }

      @Override
      public final void run() {

         setActive(true);
         setException(null);

         try {
            runImpl();
         }
         catch (Exception e) {
            setException(e);
         }
         finally {
            setActive(false);
         }

      }

      protected void runImpl() {
         System.out.println("Before");

         try {
            Thread.sleep(10000);
         } catch (InterruptedException e) {
            e.printStackTrace();
         }

         throw new RuntimeException("Some exception occurred");

         //System.out.println("After");
      }
   }

   static ThreadPoolExecutor executor = (ThreadPoolExecutor) Executors.newFixedThreadPool(1);

   static FutureTask<?> future;

   static Work work;

   public static void main(String[] args) {

      for(int i=0; i<10; ++i) {
         executor.submit(new Stub());
      }

      work = new Work();
      future = (FutureTask<?>) executor.submit(work);

      while(true) {

         System.out.println(String.format("future.done = %s, future.cancelled = %s", future.isDone(), future.isCancelled()));
         System.out.println(String.format("work.active = %s, work.exception = %s", work.isActive(), work.getException()));
         System.out.println();

         try {
            Thread.sleep(500);
         } catch (InterruptedException e) {
            e.printStackTrace();
         }

      }

   }
}

2 个答案:

答案 0 :(得分:1)

我通常使用数据流队列来通知异步活动的状态变化。

答案 1 :(得分:0)

如果你继承FutureTask,也许它会起作用。这会产生一些像这样的代码(如果我理解一切正确的话):

package experiment;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.FutureTask;

public class Work implements Runnable{

    @Override
    public void run() {
        try {
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        throw new RuntimeException("Some exception occurred");
    }

    public static void main(String[] args){
        Work work = new Work();
        MyFutureTask<Object> future = new MyFutureTask<Object>(work, null);
        ExecutorService service = Executors.newCachedThreadPool();
        service.submit(future);

         while(true) {

             System.out.println(String.format("future.done = %s, future.cancelled = %s", future.isDone(), future.isCancelled()));
             System.out.println(String.format("work.active = %s, work.exception = %s", future.isActive(), future.retrieveExeption()));
             System.out.println();

             try {
                Thread.sleep(500);
             } catch (InterruptedException e) {
                e.printStackTrace();
             }

          }

    }
}

class MyFutureTask<A> extends FutureTask<A> {

    private Exception ex;

    @Override
    protected void done() {
        super.done();
        try {
            if (!isCancelled()) get();
        } catch (ExecutionException e) {
            // Exception occurred, deal with it
            ex = e;
        } catch (InterruptedException e) {
            // Shouldn't happen, we're invoked when computation is finished
            throw new AssertionError(e);
        }
    }

    public boolean isActive(){
        return !this.isDone() && !this.isCancelled();
    }

    @Override
    protected boolean runAndReset(){
        this.ex = null;
        return super.runAndReset();
    }

    @Override
    public void run(){
        this.ex = null;
        super.run();
    }

    public Exception retrieveExeption(){
        return ex;
    }

    public MyFutureTask(Runnable runnable, A result) {
        super(runnable, result);
    }

}

它仍然是很多代码,但您可以再次重用MyFutureTask。

How to catch exceptions in FutureTask

中描述了这种异常处理方式