Question

Scénario

J'ai cette classe, disons Foo, dont le seul travail est de séquentiellement exécuter un ensemble de tâches. simple, de sons, non? Eh bien, tous de ces tâches sont exécutées dans leur propre thread séparé . Au lieu d'appeler simplement Thread.join() sur chaque tâche d'assurer l'exécution séquentielle, il utilise un ReentrantLock et Condition. Par exemple,

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

Après chaque tâche, waitForNotification() est appelé et attend une autre classe, disons Bar, réveiller . Le seul travail pour Bar est de gérer une réponse qui informe l'application si la tâche a passé ou a échoué . Cela étant dit, il fera l'une des deux choses:

  1. Annuler le fil complètement (à savoir getTask().cancel)
  2. Wake le fil (à savoir getCondition().signal)

Point 2 fonctionne très bien, mais l'article 1 ne pas . Par exemple,

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

Au lieu de annulant le fil , il semble juste interruption , ce qui provoque Foo de poursuivre son exécution. Désolé pour la verbosité, mais je voulais vous donner les gars une image claire. Toutes les suggestions?

Était-ce utile?

La solution

AFAIK, les discussions ne supportent pas la notion de « annulation » de la boîte. Vous devez cuire dans la logique de « annuler » vos tâches spécifiques lorsque votre fil est interrompue. Cela se fait généralement en vérifiant l'état d'interruption du fil lors de l'exécution de votre tâche / travail et sortir à proprement si l'état a été réglé à vrai (ce qui arrive lorsque vous appelez d'interruption).

Un échantillon extrait qui peut vous aider. A lire également, vers le bas des fils proprement fermeture .

Autres conseils

À moins que la tâche arrête lorsqu'il est interrompu, le drapeau sera juste ensemble et rester fixé jusqu'à la fin de tâche ou décide d'arrêter.

double possible de http :. //www.google.co.uk/search q = comment + I + arrêt + a + fil + dans + Java 28.000.000 résultats

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top