import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.Callable;
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";
try {
System.out.println("Started..");
/*for (int i=0;i<10000;i++) {
if (i % 2 == 0) {
System.out.println("Even");
}
}*/
boolean flag = true;
while(flag) {
}
System.out.println("Finished!");
s = "Done";
}
catch (RuntimeException e) {
s = "RuntimeException";
}
catch (Exception e) {
s = "Exception";
}
finally {
}
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()), 5, TimeUnit.SECONDS);
executor.shutdown();
Iterator<Future<String>> iter = result.iterator();
while (iter.hasNext()) {
System.out.println("Came here");
Future<String> fut = iter.next();
System.out.println(fut.get());
}
}
}
有没有办法可以阻止线程执行无限循环?
答案 0 :(得分:7)
是的,您可以将flag
(或逻辑&&
)替换为!Thread.currentThread().isInterrupted()
。
这样,当任务为canceled,时,循环将被终止。
循环看起来像这样:
while(!Thread.currentThread().isInterrupted() && flag) {
/* Do work. */
}
使用应该是这样的:
ExecutorService executor = Executors.newSingleThreadExecutor();
Future<String> task = executor.submit(new Task());
String str;
try {
str = task.get(5, TimeUnit.SECONDS);
} finally {
task.cancel(true);
}
答案 1 :(得分:0)
考虑在synchronized (this) { this.wait() }
内使用sleep
代替call()
,然后在外部设置布尔flag
(可能直接或通过flag()
方法;通过直接访问确保您的标志变量为volatile
)调用task.notifyAll()
以唤醒休眠线程(确保您的任务对象是本地变量而不是匿名,以便您可以调用方法它,并在Task
)内标记一个类属性。
它也会更有效率,因为循环浪费不必要的循环 - 确切的机制被称为'保护块'(http://java.sun.com/docs/books/tutorial/essential/concurrency/guardmeth.html)。当您从等待中醒来时,请测试标志变量,以确保它已设置。
编辑:更仔细地查看原始问题,并使用现有的代码和原则创建了一个示例(有一种方法可以让猫皮肤化:))。试试这个 - 这里的循环由于当前线程的中断状态而退出,该状态因超时而被取消:
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();
}
}
}
}