【问题标题】:Future.cancel and ReentrantLocksFuture.cancel 和 ReentrantLocks
【发布时间】:2011-08-14 18:37:15
【问题描述】:

场景

我有这个类,比如说Foo,它唯一的工作就是顺序执行一组任务。听起来很简单,对吧?嗯,所有这些任务都在它们自己的独立线程中执行。它不是简单地在每个任务上调用Thread.join() 以确保顺序执行,而是使用ReentrantLockCondition。例如,

public class Foo
{
    private final Lock lock;
    private final Condition condition;
    private Future<?> task;

    public Foo()
    {
        lock = new ReentrantLock();
        condition = lock.newCondition();

        run();
    }

    /**
     * Runs Foo
     */
    public void run()
    {
        Runnable runnable = new Runnable()
        {
            @Override
            public void run()
            {
                lock.lock();
                try
                {
                    // do tasks
                }
                finally
                {
                    lock.unlock();
                }

            }
        };

        // Submit task
        task = Executors.newSingleThreadExecutor().submit(runnable);
    }

    /**
     * Blocks execution until signal is received
     */
    public void waitForNotification()
    {
        try
        {
            condition.await();
        }
        catch (InterruptedException e)
        {
        }
    }

    /**
     * Gets the lock
     * 
     * @return Lock
     */
    public final Lock getLock()
    {
        return lock;
    }

    /**
     * Gets the condition
     * 
     * @return Condition
     */
    public final Condition getCondition()
    {
        return condition;
    }

    /**
     * Gets the sender's task
     * 
     * @return Task
     */
    public Future<?> getTask()
    {
        return task;
    }
}

在每个任务之后,waitForNotification() 被调用并等待另一个类,比如Bar,以唤醒它Bar 的唯一工作是处理通知应用程序任务是通过还是失败的响应。话虽如此,它将做以下两件事之一:

  1. 完全取消话题(即getTask().cancel
  2. 唤醒线程(即getCondition().signal

第 2 项工作正常,但第 1 项不行。例如,

public class Bar
{
    private Foo foo;

    // doesn't work!
    public void handleFailed()
    {
        // Cancel task
        foo.getTask().cancel(true)
    }

    public void handlePassed()
    {
         // Signal waiting Foo
         foo.getLock().lock();
         try
         {
            foo.getCondition().signal();
         }
         finally
         {
            foo.getLock().unlock();
         }
    }
}

而不是取消线程,它似乎只是中断它,这导致Foo 继续执行。抱歉冗长,但我想给你们一个清晰的画面。有什么建议吗?

【问题讨论】:

    标签: java conditional-statements future reentrantlock


    【解决方案1】:

    AFAIK,线程不支持开箱即用的“取消”概念。当您的线程被中断时,您必须在逻辑中“取消”您的特定任务。这通常通过在运行任务/作业时检查线程的中断状态来完成,如果状态已设置为 true(当您调用中断时会发生这种情况),则干净地退出。

    A sample snippet 可能帮助你。另请阅读,shutting down threads cleanly

    【讨论】:

      【解决方案2】:

      除非任务在中断时停止,否则标志将被设置并保持设置直到任务结束或决定停止。

      http://www.google.co.uk/search?q=how+do+I+stop+a+thread+in+Java 28,000,000 个结果可能重复。

      【讨论】:

      • @Peter:为什么getTask().cancel(true) 不停止线程?它似乎只是中断了它,这在 API 中并不清楚。
      • @sthupashmaht 没有干净的方法来取消线程,因为线程可以持有锁。
      • javadoc 说mayInterruptIfRunning - true if the thread executing this task should be interrupted; 它甚至不保证中断线程。 (如果它没有运行它就不会)
      • @Peter:我觉得这不是解决这个问题的最佳方法。有什么建议吗?
      • @Victor Sorokin,Thread.stop() 将终止一个线程并正确释放所有锁,但是没有简单的方法可以在不使系统处于潜在不一致状态的情况下做到这一点。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-04-16
      • 1970-01-01
      • 2019-06-16
      • 2018-12-07
      • 2018-07-25
      相关资源
      最近更新 更多