Stop an infinite loop in an ExecutorService task

荒凉一梦 提交于 2019-11-29 00:13:01

Yes, you can replace flag (or logically &&) with !Thread.currentThread().isInterrupted().

This way, when the task is canceled, the loop will be terminated.

The loop would look something like this:

while(!Thread.currentThread().isInterrupted() && flag) {
  /* Do work. */
}

Use should be something like this:

ExecutorService executor = Executors.newSingleThreadExecutor();
Future<String> task = executor.submit(new Task());
String str;
try {
  str = task.get(5, TimeUnit.SECONDS);
} finally {
  task.cancel(true);
}

Think about using synchronized (this) { this.wait() } instead of sleep inside call(), and then when you set the boolean flag externally (perhaps directly or via a flag() method; with direct access make sure your flag variable is volatile) call task.notifyAll() to wake up the sleeping thread (make sure your task object is a local variable instead of having it anonymous so that you can call methods on it, and make flag a class attribute within Task).

It'll also be more efficient like that because loops waste cycles needlessly -- the exact mechanism is called a 'guarded block' (http://java.sun.com/docs/books/tutorial/essential/concurrency/guardmeth.html). When you wake up out of the wait, test for the flag variable just to make sure it was set.

Edit: looked at the original question more closely and created an example using the existing code and principles (there's more than one way to skin a cat :)). Try this -- the loop here exits due to the interrupted status of the current thread, which has been canceled due to timeout:

package ett;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;

class Task implements Callable<String> {
    public String call() throws Exception {
        String s = "initial";
        System.out.println("Started..");
        for (int i=0;;i++) {
            if (i % 2 == 0) {
                System.out.println("Even");
            }
            Thread.yield();
            if (Thread.interrupted()) break;
        }
        System.out.println("Finished!");
        s = "Done";

        return s;
    }
}

public class ExecutorServiceTest {

    public static void main(String[] args) throws Exception {
        ExecutorService executor = Executors.newSingleThreadExecutor();
        List<Future<String>> result = executor.invokeAll(Arrays.asList(new Task()), 1, TimeUnit.SECONDS);
        executor.shutdown();

        System.out.println("came here");

        for (Future<String> f : result) {
            try {
                System.out.println(f.get());
            } catch (CancellationException e) {
                e.printStackTrace();
            }
        }
    }
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!