2017-09-29 4 views
1

미래를위한 하나를 충족하는 경우에 실행중인 다른 미래의 작업을 종료 . 내가하고있는 일은 동기식이다. 나는 그것을 병렬로하고 싶고 java에서 Future를 사용하여 끝낼 수 있다는 것을 알았다. URL에서 파일을 다운로드 할 때 apache.commons.io를 사용하고 있습니다. 여기에 코드입니다 :는 조건이 자바 8</p> <p>내가 사랑하는 서버에서 로그 파일을 이러한 로그 파일에서 특정 텍스트를 검색 다운로드 할 음식물을 쓰기 위해 노력하고있어 사용 작업

ExecutorService executorService = Executors.newCachedThreadPool(); 
    List<Future<XCluster>> clusterFutures = new ArrayList<>(); 
    for(XCluster cluster: clusters) { 
     clusterFutures.add(executorService.submit(() -> { 
      return downloadAndSearch(textToSearch, cluster); 
     })); 
    } 
    //For now I'm not doing anything with returned value from Future 

하지만 지금은 주어진 검색이 서버 중 하나에서 발견 될 것으로 예상된다와 같은 다른 다운로드 검색 작업이 미래에서 시작 종료합니다. 따라서 내가 시작한 다른 미래 작업을 계속할 필요가 없습니다. 어느 누구도 이것을 할 수있는 방법을 제안 할 수 있습니까? 나는 자바 8을 사용하고, 다른 옵션도 환영합니다. 미리 감사드립니다!

답변

1

ExecutorService에는 모든 스레드를 중지하고 서비스를 종료하는 shutdownNow 메서드가 있습니다.

편집 : 내가 생각했던대로 스레드를 중지 할 수 없습니다 참조로

나는 shutdownNow의 몇 가지 실험을했고. AFAIK 인터럽트()를 사용하지만 모든 스레드가 인터럽트에 반응하지는 않습니다.

그래서 내가 가지고 올 수있는 최선의 대안 : 당신이 의사 소통을 하나 개의 표시 인스턴스를 공유해야 시작

public static class Indicator{ 

    private boolean isReady = false; 

    public void ready(){ 
     isReady = true; 
    } 

    public boolean isReady(){ 
     return isReady; 
    } 
} 

스레드 :

먼저, 지표 클래스를 만들 수 있습니다. 그래서 당신은이 같은 호출 가능을 만들 수 있습니다

public static class Processor implements Callable<Integer> { 

    private volatile Indicator indicator; 

    private Integer number; 

    public Processor(Integer integer, Indicator isReady){ 
     this.number = integer; 
     this.indicator = isReady; 
    } 

    @Override 
    public Integer call() throws Exception { 
     System.out.println("Thread started:" + Thread.currentThread().getId()); 
     int counter = 0; 
     while (!indicator.isReady &&counter < number) { 
      // Make complicated things 
      Math.sin(counter); 
      counter++; 
     } 
     if(indicator.isReady){ 
      //another thread finished 
      //delete resources 
      System.out.println("Thread interrupted: " + Thread.currentThread().getId() + " " + counter); 
      return -1; 
     } else { 
      System.out.println("Thread finished: " + Thread.currentThread().getId() + " " + counter); 
      indicator.ready(); 
      return counter; 
     } 
    } 
} 

이 방법을 첫 번째 스레드가 다른 사람을 중지 할 수 있습니다 그들은 himselves 후 청소 준비가되었을 때.

public static void main(String[] args) throws ExecutionException, InterruptedException { 
    ExecutorService executorService = Executors.newCachedThreadPool(); 
    List<Future<Integer>> clusterFutures = new ArrayList<>(); 
    Indicator indicator = new Indicator(); 
    clusterFutures.add(executorService.submit(new Processor(100, indicator))); 
    clusterFutures.add(executorService.submit(new Processor(10000, indicator))); 
    clusterFutures.add(executorService.submit(new Processor(10000000,indicator))); 
} 

샘플 출력 :

Thread started:11 
Thread started:12 
Thread finished: 11 100 
Thread interrupted: 12 1001 
Thread started:13 
Thread interrupted: 13 0 

(!) 참고가 : 참조 된 클래스는 정적 내부 클래스 그냥에서 실험을 할 쉬웠다 될 필요가 없습니다 다음과 같이

나는이 시도 하나의 파일. 코드의 관점에서

+0

감사합니다. 마침내 다른 스레드를 종료 할 때 실행되는 코드 블록을 갖는 방법이 있습니까? 다른 선물에서 다운로드 한 파일을 정리해야합니다. – user3539951

0

는, 가장 간단한 솔루션은 모든 선물 취소 종료 스레드 것입니다 :

final ExecutorService executorService = Executors.newCachedThreadPool(); 
    final ExecutorService shutdownService = Executors.newSingleThreadExecutor(); 
    List<Future<XCluster>> clusterFutures = new ArrayList<>(); 
    for(XCluster cluster: clusters) { 
     clusterFutures.add(executorService.submit(() -> { 
      boolean cancelOthers = false; 
      try { 
       XCluster result = downloadAndSearch(textToSearch, cluster); 
       cancelOthers = yourPredicateOfSuccess(); 
       return result; 
      } finally { 
       if (cancelOthers) { 
       shutdownService.execute(() -> { 
        executorService.shutdownNow(); 
       }); 
       } 
      } 
     })); 
    } 

다른 스레드와 시도가-마지막으로 중요한이 확실하게 때문에를 당신은하지 않습니다 거의 성공한 메소드 실행을 취소하십시오.

+0

감사합니다, 나는이 접근 방식을 내가 다른 미래의 시스템 종료를 시도했지만 그게 작동하지 않습니다. 스레드는 shutdownNow()를 호출 한 후에도 계속 실행됩니다. – user3539951

관련 문제