如何在Executor中调度Callable

时间:2014-06-02 23:45:01

标签: java executorservice

我正在尝试安排等待某种情况发生的线程。如果condition为true,则返回一些结果,否则再安排自己在一段延迟后执行。为实现此目的,我使用Executors来安排Callable<Boolean>,但在第二次重新安排后它会挂起。

 final ExecutorService executor = Executors.newFixedThreadPool(2);
    final MutableBoolean status = new MutableBoolean(false);

    new Thread(new Runnable() {
        @Override
        public void run() {
            System.out.println("Waiting now to set status");
            try {
                Thread.sleep(5*1000);
                System.out.println("status is now true");
                status.setValue(true);
            } catch (InterruptedException e) {
            }

        }
    }).start();

    Future<Boolean> future = executor.submit(new Callable<Boolean>() {
        public int count=0;
        @Override
        public Boolean call() throws Exception {
            if(status.isTrue()){
                System.out.println("Condition has become true now");
                return status.booleanValue();
            } else {
                System.out.println("Not true yet, count" + count++ + " Rescheduling");
                Future<Boolean> future = executor.submit(this);
                return future.get();
            }
        }
    });

    boolean finalStatus = future.get();
    System.out.println("Final status" + finalStatus);

输出:

Waiting now to set status
Not true yet, count0 Rescheduling
Not true yet, count1 Rescheduling
status is now true

有关可能出现的问题的任何建议?

由于

2 个答案:

答案 0 :(得分:1)

您创建了一个大小为2的线程池。然后,您从池中运行的作业(递归地)向该池提交任务,并等待它们完成(调用future.get())。

答案 1 :(得分:1)

使用executor.submit(this)每次都会向线程池提交一个新任务,线程池不会(也不应该)检查线程池中的线程是否已经执行了相同的任务。由于线程池只有两个线程,因此两个线程都将非常快速地使用并无限期地等待。

脏修复如下:

    @Override
    public Boolean call() throws Exception {
        while (true) {
            if(status.get()){
                System.out.println("Condition has become true now");
                return status.get();
            }
        }
    }

但这会导致非常高的CPU使用率。正如Brett Okken建议的那样,使用预定的执行服务。或者,如果状态在不久的将来应始终更改为true,请使用CountDownLatch等等屏障立即对状态更改做出反应。