2010-03-01 32 views
6
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()); 
     } 
    } 
} 

有沒有辦法讓我可以停止執行無限循環的線程?在ExecutorService任務中停止無限循環

回答

7

是的,您可以用!Thread.currentThread().isInterrupted()替換flag(或邏輯&&)。

這樣,當任務爲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); 
} 
0

考慮使用synchronized (this) { this.wait() },而不是sleepcall(),然後當你設置布爾(可能直接或通過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(); 
      } 
     } 
    } 
}