`
yangdong
  • 浏览: 66618 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

FutureTask.isDone() 的返回问题

    博客分类:
  • Java
阅读更多
FutureTask.isDone() 方法在 cancel(boolean) 方法被调用后会立即返回 true。这在很多情况下不会是我们想要的。我们可能需要确保 FutureTask 所代表的后台线程已经执行完毕了再做一些事情。比如须要做一些资源清理、解锁等等。

关于这一点,Sun Forum 里有一个帖子与此相关。这个帖子的楼主最后给出了一个会破坏 cancel(boolean) 方法语义约定的解决方案。我个人觉得还有改进的余地。可以不去干扰 cancel 和 isDone 方法的实现,转而去添加一个新方法 await。在这个方法里实现我们需要的功能:不管任务执行过程当中发生了什么(比如用户取消),只有当 run 方法真正返回时这个方法才返回。如果需要无阻塞的探测方法,可以再添加一个 isDead。
public class FutureTask2<V> extends FutureTask<V> {

    public FutureTask2(Callable<V> callable) {
        super(callable);
    }

    public FutureTask2(Runnable runnable, V result) {
        super(runnable, result);
    }

    public void await() throws InterruptedException {
        finishLatch.await();
    }

    public void await(long timeout, TimeUnit unit) throws InterruptedException {
        finishLatch.await(timeout, unit);
    }

    public boolean isDead() {
        return finishLatch.getCount() == 0;
    }

    @Override
    public void run() {
        try {
            super.run();
        } finally {
            finishLatch.countDown();
        }
    }

    private final CountDownLatch finishLatch = new CountDownLatch(1);

}


同样的问题也存在于 SwingWorker 中,而且这个问题更加棘手。因为 NetBeans 附带的 appframework 就使用了 SwingWorker 作为 Task 的实现基类(尽管 appframework 把 SwingWorker 单独抽到一个包里了,但其实它的源码跟 JDK6 里面的一样)。如果你使用 appframework 提供的 Task 来处理 Swing 的异步任务的话,那么在感觉很爽的同时也会为这个 isDone 的问题而头疼。只有当我们的后台方法能很快的检测到任务被取消了,并且能很快地完成任务的退出,否则我们就有麻烦了。如果任务没有办法立刻取消,那么我们会看到 Task 的状态是已完成并且是已取消,但是后台线程还在工作。而且我们还没有任何的办法知道后台线程是不是真的死掉了。因为 Thread 类实例被 Task 类通过 FutureTask 给包裹起来了。

但是 SwingWorker 把 run() 方法做成 final 了。所以连带 Task 也没办法找到一个合适的解决方案。如果您恰好对此感兴趣,欢迎探讨!



我的思路一直局限在 run 方法上。如果我们在 SwingWorker 的 doInBackground() 里面来做应该可以达到目的的。一样的道理,这也应该适用于 Task。SwingWorker 的解决代码:
public class MySwingWorker extends SwingWorker<Void, Void> {

    public void await() throws InterruptedException {
        finishLatch.await();
    }

    public void await(long timeout, TimeUnit unit) throws InterruptedException {
        finishLatch.await(timeout, unit);
    }

    public boolean isDead() {
        return finishLatch.getCount() == 0;
    }

    @Override
    protected Void doInBackground() throws Exception {
        try {
            Thread.sleep(1000); // 模拟耗时工作
        } finally {
            finishLatch.countDown();
        }
        return null;
    }

    private final CountDownLatch finishLatch = new CountDownLatch(1);

}


也许有人会有疑问,无论是在前面的 FutureTask2 还是这里的 MySwingWorker,在锁上调用 countDown() 的时候都没有做检查。如果 FutureTask2 或者 MySwingWorker 被重复调用怎么办,是不是会导致锁的状态被破坏?不会的。因为 FutureTask 这个基类会保证如果重复调用 run(),那么第二次以及后续的调用都不会触发 FutureTask 所包裹的 Callable 或者 Runnable。也就是说 FutureTask 会安静地忽略除了第一次以外的调用。一样地,SwingWorker 也忽略除了第一次以外的调用。
分享到:
评论

相关推荐

    FutureTask学习

    - `boolean isDone()`:检查任务是否已经完成(包括正常完成、被取消或出现异常)。 - `V get()`:等待任务完成并返回结果。如果任务尚未完成,此方法会阻塞直到任务完成。 - `V get(long timeout, TimeUnit unit...

    揭密FutureTask.docx

    3. `boolean isDone()`:判断任务是否已完成,包括正常完成、异常结束或被取消。 4. `V get()`:阻塞直到任务完成,然后返回结果,如果任务被取消或出现异常,则抛出相应的异常。 5. `V get(long timeout, TimeUnit ...

    多线程执行完后主程序再执行(包括需要子线程返回结果)

    if (futureTask.isDone()) { System.out.println("Task completed."); } if (futureTask.isCancelled()) { System.out.println("Task cancelled."); } ``` 在实际应用中,`FutureTask`经常与`...

    Java 多线程与并发(17-26)-JUC线程池- FutureTask详解.pdf

    - `isDone()`:检查任务是否已经完成。如果任务已经正常完成、因异常终止或被取消,则返回`true`。 - `get()`:获取任务的计算结果。如果任务尚未完成,则阻塞等待直至完成。如果任务被取消,则抛出`...

    Java分布式应用学习笔记05多线程下的并发同步器

    futureTask.isDone()) { try { Thread.sleep(500); System.out.println("东方不败:“等兄弟回来了,我就和小弟弟告别……颤抖……”"); } catch (InterruptedException e) { e.printStackTrace(); } } ...

    比较java中Future与FutureTask之间的关系

    3. `isDone()`: 判断任务是否完成,如果任务完成则返回true。 4. `get()`: 获取执行结果,这个方法会产生阻塞,会一直等到任务执行完毕才返回。 5. `get(long timeout, TimeUnit unit)`: 获取执行结果,如果在指定...

    Java中Future、FutureTask原理以及与线程池的搭配使用

    3. `boolean isDone()`:检查任务是否已完成,无论成功、失败还是被取消。 4. `V get()`:等待任务完成并返回结果。如果任务尚未完成,调用者将被阻塞,直到结果可用。 5. `V get(long timeout, TimeUnit unit)`:...

    简谈java并发FutureTask的实现

    2. `isDone()`: 检查任务是否已经完成,包括正常完成、抛出异常或被取消。 3. `cancel()`: 尝试取消任务。如果任务已经开始执行,则无法保证其会被立即停止,但可以通过`mayInterruptIfRunning`参数尝试中断正在运行...

    【Java】Callable创建线程用到的适配器模式(csdn)————程序.pdf

    FutureTask提供了对Callable结果的访问和管理,包括获取结果(get()方法)和检查任务是否完成(isDone()和isCancelled()方法)。 3. 创建Thread实例:将FutureTask作为参数传递给Thread的构造函数,这样线程就可以...

    java多线程返回值使用示例(callable与futuretask)

    `Future`接口提供了多种方法来检查任务的状态,如`isDone()`、`isCancelled()`以及获取结果等。在上述示例中,我们使用了`get()`方法来获取结果,如果任务尚未完成,它会阻塞直到结果可用。如果任务已取消或抛出异常...

    Java并发基础.docx

    task.isDone()) { System.out.println(task.get().toString()); } } } ``` 4. 后台线程(守护线程): 后台线程,或称为守护线程,是那些为其他线程提供服务并在所有用户线程结束后才结束的线程。它们通常用于...

    java多线程编程同步器Future和FutureTask解析及代码示例

    3. `boolean isDone()`:如果任务已经完成(无论正常结束、异常结束或被取消),返回`true`。 4. `V get()`:如果需要,等待计算完成并获取结果。如果计算未完成,此方法将阻塞直到有结果可用。 5. `V get(long ...

    31 凭票取餐—Future模式详解.pdf

    在Java中,`java.util.concurrent.Future`接口定义了几个方法,如`get()`用于获取结果,`isDone()`检查任务是否完成,`cancel()`取消任务等。在使用Future模式时,我们需要创建一个实现了Callable接口的类,该类的...

    线程超时死掉

    boolean isDone() 任务是否已经完成。需要注意的是如果任务正常终止、异常或取消,都将返回true V get() throws InterruptedException, ExecutionException 等待任务执行结束,然后获得V类型的结果。...

    Callable和Future.doc

    3. `boolean isDone()`:判断任务是否已经完成,无论是正常结束、异常结束还是被取消,只要任务不再运行,都会返回 true。 4. `V get()`:阻塞当前线程,直到任务完成,然后返回结果。如果任务在执行过程中抛出异常...

    future.zip

    - `isDone()`:检查计算是否已完成。 - `isCancelled()`:检查任务是否被取消。 - `cancel(boolean mayInterruptIfRunning)`:尝试取消执行中的任务。 2. **`Future`的实现类** 在Java中,`FutureTask`是`Future`的...

    java.util.concurrent.uml.pdf

    它提供了get方法,用于获取计算结果,以及cancel方法来取消任务,还有isDone和isCancelled等方法用于查询任务状态。 FutureTask是一个实现了Future和Runnable接口的类,它是一个可以包装Callable或Runnable任务的可...

    concurrent-all-in-one.pdf

    - 获取结果:`get()`方法阻塞直到任务完成,`isDone()`检查任务状态。 - 取消任务:`cancel()`方法尝试取消任务,如果任务已经开始则可能无法取消。 6. **ExecutorService管理** - 创建:`Executors`工厂类提供...

    java并发(二十四)多线程结果组装

    `get()`方法用于阻塞直到任务完成并返回结果,而`isDone()`则检查任务是否已经完成。如果任务未完成,调用`get()`会阻塞当前线程,直到结果可用。 2. **Callable和Runnable**:在多线程环境中,任务可以表示为`...

    简析Java中的util.concurrent.Future接口

    如果计算完成,无论成功还是失败,`isDone()`都会返回`true`。这是监控任务状态的一个有用工具。 4. `cancel(boolean mayInterruptIfRunning)`:此方法用于尝试取消正在进行的计算。如果`mayInterruptIfRunning`为`...

Global site tag (gtag.js) - Google Analytics