Подумайте об использовании synchronized (this) { this.wait() }
вместо sleep
внутри call()
, а затем, когда вы устанавливаете логическое значение flag
извне (возможно, напрямую или с помощью метода flag()
; при прямом доступе убедитесь, что ваша переменная флага равна volatile
) вызовите task.notifyAll()
, чтобы разбудить спящий поток (убедитесь, что ваш объект задачи является локальной переменной, а не анонимным, чтобы вы могли вызывать методы для него, и сделайте флаг атрибутом класса в Task
).
Это также будет более эффективным, потому что циклы ненужных циклов излишне - точный механизм называется «защищенным блоком» (http://java.sun.com/docs/books/tutorial/essential/concurrency/guardmeth.html). Когда вы выходите из ожидания, проверьте переменную flag просто чтобы убедиться, что он установлен.
Редактировать: более внимательно посмотрел на исходный вопрос и создал пример, используя существующий код и принципы (существует более одного способа обнажить кошку :)). Попробуйте это - цикл здесь завершается из-за прерванного состояния текущего потока, которое было отменено из-за тайм-аута:
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();
}
}
}
}