سؤال

Scenario

I have this class, let's say Foo, whose only job is to sequentially execute a set of tasks. Sounds simple, right? Well, all of these tasks are executed in their own separate thread. Instead of simply calling Thread.join() on each task to ensure sequential execution, it uses a ReentrantLock and Condition. For instance,

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;
    }
}

After every task, waitForNotification() is called and waits for another class, let's say Bar, to wake it up. The only job for Bar is to handle a response that informs the application whether the task has passed or failed. That being said, it will do one of two things:

  1. Cancel the thread altogether (i.e. getTask().cancel)
  2. Wake the thread (i.e. getCondition().signal)

Item 2 works just fine, but Item 1 doesn't. For instance,

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();
         }
    }
}

Instead of cancelling the thread, it just seems to interrupt it, which causes Foo to continue its execution. Sorry for the verbosity, but I wanted to give you guys a clear picture. Any suggestions?

هل كانت مفيدة؟

المحلول

AFAIK, threads don't support the notion of "cancelling" out of the box. You have to bake in the logic to "cancel" your specific tasks when your thread is interrupted. This is typically done by checking the interrupt status of the thread when running your task/job and exit out cleanly if the status has been set to true (which happens when you call interrupt).

A sample snippet which might help you out. Also read, shutting down threads cleanly.

نصائح أخرى

Unless the task stops when interrupted, the flag will just be set and remain set until the task ends or decides to stop.

Possible duplicate of http://www.google.co.uk/search?q=how+do+I+stop+a+thread+in+Java 28,000,000 results.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top