2010-03-01 2 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()으로 바꿀 수 있습니다.

이렇게하면 작업이 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 외부로 (직접 또는 flag() 방법을 통해 직접 액세스 할 수 있음) 플래그가 volatile인지 확인하십시오.로 전화하십시오.잠자는 스레드를 깨우려면 (작업 개체가 익명으로 처리되지 않도록 로컬 변수를 사용하여 메서드를 호출하고 플래그를 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(); 
      } 
     } 
    } 
}