监视对象池工作者的状态

时间:2013-02-27 17:00:09

标签: java multithreading threadpool pool concurrent-programming

我已经从另一个类中创建了这个线程,用于在完成时读取执行程序的状态,并在失败时取消其余的任务。任务是可运行的

如果发现任何故障,总体状态必须为1或失败

final CompletionService completionService = new ExecutorCompletionService(getExecutorService());
final List<Future> futures = new ArrayList<Future>();

    FutureTask<Integer> tasks = new FutureTask<Integer>(new Callable<Integer>() {

        public Integer call() {

            int status = 0;
            boolean fail = false;

            try {
                for (int i = 0; i < 10; i++) {

                    MyRunnable resultObj = null;

                    try {
                        resultObj = (MyRunnable) completionService.take().get();
                    } catch (CancellationException e) {
                        // Skip it ..
                    }

                    if (!fail) {
                        status = resultObj.getStatus();

                        if (status == 1) {
                            fail = true;
                            for (Future future : futures) {
                                if (!future.isCancelled() && !future.isDone())
                                    future.cancel(true); // cancel pending tasks including running tasks 
                            }
                        }
                    }
                }
            } catch (Exception e) {
                 e.printStackTrace();
            }

            return status;
        }

            });

线程已启动 -

ExecutorService pool = Executors.newSingleThreadExecutor();
pool.submit(tasks);

Down,Object是从池中借来的,它是一个阻塞调用,我将池大小设置为3 因此,最初3名MyRunnable工作人员立即获得了成功。当每个工人完成时,他们会重复使用以完成剩余的任务。

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

    MyRunnable myRunnable = null;
    myRunnable = (MyRunnable) this.getGenericObjectPool().borrowObject();

    set myRunnable ..

    futures.add(completionService.submit(myRunnable, myRunnable));

}

while (!tasks.isDone()) {

        try {
            Thread.sleep(Global.WaitTime());            
        } catch (InterruptedException iex) {            
        }

}

finalStatus = tasks.get();
pool.shutdown();

GenericObjectPool配置为重用对象。我通过强制第一个Thread失败并将其状态设置为1来模拟IDE中的测试。但问题是,一旦它被释放,它就被borrowObject()重用,并且监视Thread看到了已设置状态的已更改对象返回0作为激活新对象的一部分,由GenricObjectPool完成。

所以,我无法从失败的线程中读取状态。 MyRunnable不可调用,所以我不得不使用completionService.submit(obj,obj)来欺骗Runnable

如果将Pool大小设置为10或更大,则不会发生此问题,因为没有任何对象将被重用,并且我将成功读取每个对象的状态,但这不是一个选项。

1 个答案:

答案 0 :(得分:0)

我为Runnable创建了一个CallableDecorator来解决这个问题。现在即使使用GenericObjectPool,我也有适当的返回值。由于现在对于读取状态没有依赖于Pool对象,即使重用对象也不会导致状态重置 -

因此,代码中有2个更改 - 更改

futures.add(completionService.submit(myRunnable, myRunnable));

futures.add(completionService.submit(new CallableDecorator(myRunnable)));

添加新课程

public class CallableDecorator implements Callable {

       IRunnable r;

       public CallableDecorator(IRunnable r) {

           this.r = r;
       }

       public Integer call() {

           r.run();
           return r.statusCode();
       }
}

interface IRunnable extends Runnable {
     public Integer statusCode();
}

类似地,必须将resultObj更改为整数,以便在监视器线程中获取其值。