문제

우선, 나는 API java.util.concurrent를 처음 접한다고 말해야합니다.

나는 무엇을하고 싶습니까?

기본적으로 2 개의 개별 처리를 실행하는 Java 응용 프로그램이 있습니다 ( MyFirstprocess, mysecondprocess), 그러나 이러한 처리는 동시에 실행해야합니다.

그래서 나는 그렇게하려고 노력했습니다.

public void startMyApplication() {
    ExecutorService executor = Executors.newFixedThreadPool(2);
    FutureTask<Object> futureOne = new FutureTask<Object>(myFirstProcess);
    FutureTask<Object> futureTwo = new FutureTask<Object>(mySecondProcess);
    executor.execute(futureOne);
    executor.execute(futureTwo);
    while (!(futureOne.isDone() && futureTwo.isDone())) {
        try {
            // I wait until both processes are finished.
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    logger.info("Processing finished");
    executor.shutdown();
    // Do some processing on results
    ...
}

MyFirstprocess 그리고 mysecondprocess 구현하는 수업입니다 Callable<Object>, 및 모든 처리가 Call () 메소드에서 이루어지는 경우.

그것은 잘 작동하지만 그것이 올바른 방법인지 확실하지 않습니다. 내가 원하는 것을하는 좋은 방법입니까? 그렇지 않다면, 내 코드를 향상시키기위한 힌트를 줄 수 있습니다.

도움이 되었습니까?

해결책

당신은 사용하는 것이 더 좋을 것입니다 get() 방법.

futureOne.get();
futureTwo.get();

두 가지 모두 처리를 마친 스레드에서 알림을 기다리므로 현재 사용하고있는 바쁜 시간을 절약 할 수 있습니다. 효율적이거나 우아하지 않습니다.

보너스로 API가 있습니다 get(long timeout, TimeUnit unit) 이를 통해 스레드가 잠을 자고 응답을 기다릴 때까지 최대 시간을 정의하고 계속 실행됩니다.

참조 Java API 더 많은 정보를 위해서.

다른 팁

의 사용 FutureTask 위는 견딜 수 있지만 관용적이지는 않습니다. 당신은 실제로 감싸고 있습니다 추가의 FutureTask 당신이 제출 한 것 주위 ExecutorService. 당신의 FutureTask a로 취급됩니다 Runnable 에 의해 ExecutorService. 내부적으로, 그것은 당신을 감싸고 있습니다 FutureTask-처럼-Runnable 새로운 FutureTask 그리고 그것을 당신에게 반환합니다 Future<?>.

대신, 당신은 당신의 제출해야합니다 Callable<Object> 인스턴스 a CompletionService. 당신은 두 가지를 떨어 뜨립니다 Callable비어있는 s submit(Callable<V>), 그런 다음 돌아 서서 전화하십시오 CompletionService#take() 두 번 (제출 된 각각에 대해 한 번 Callable). 해당 통화는 하나가 될 때까지 차단되고 다른 제출 된 작업이 완료됩니다.

당신이 이미 가지고 있다는 것을 감안할 때 Executor 손에 새로 구성하십시오 ExecutorCompletionService 그 주위에 당신의 작업을 떨어 뜨립니다. 회전하고 잠들지 마십시오. CompletionService#take() 작업 중 하나가 완료되거나 (실행 또는 취소 된) 또는 대기 대기 스레드가 될 때까지 차단됩니다. take() 중단됩니다.

Yuval의 해결책은 괜찮습니다. 대안으로 다음을 수행 할 수도 있습니다.

ExecutorService executor = Executors.newFixedThreadPool();
FutureTask<Object> futureOne = new FutureTask<Object>(myFirstProcess);
FutureTask<Object> futureTwo = new FutureTask<Object>(mySecondProcess);
executor.execute(futureOne);
executor.execute(futureTwo);
executor.shutdown();
try {
  executor.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
} catch (InterruptedException e) {
  // interrupted
}

이 접근법의 장점은 무엇입니까? 이 방법을 제외하고는 실제로 많은 차이가 없다. 나는이 관용구를 그 일보다 선호하는 경향이있다.

또한 get ()가 예외를 던지면 두 작업이 수행되었다고 가정하는 코드의 일부에서 끝날 수 있습니다.

invokeall (colelction ....) 메소드를 사용할 수 있습니다

package concurrent.threadPool;

import java.util.Arrays;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

public class InvokeAll {

    public static void main(String[] args) throws Exception {
        ExecutorService service = Executors.newFixedThreadPool(5);
        List<Future<java.lang.String>> futureList = service.invokeAll(Arrays.asList(new Task1<String>(),new Task2<String>()));

        System.out.println(futureList.get(1).get());
        System.out.println(futureList.get(0).get());
    }

    private static class Task1<String> implements Callable<String>{

        @Override
        public String call() throws Exception {
            Thread.sleep(1000 * 10);
            return (String) "1000 * 5";
        }

    }

    private static class Task2<String> implements Callable<String>{

        @Override
        public String call() throws Exception {
            Thread.sleep(1000 * 2);
            int i=3;
            if(i==3)
                throw new RuntimeException("Its Wrong");
            return (String) "1000 * 2";
        }

    }
}

사용하고 싶을 수도 있습니다 사이클리 배저 스레드를 동시에 시작하는 데 관심이 있거나 완료되기를 기다린 다음 추가 처리를 수행합니다. 자세한 내용은 Javadoc을 참조하십시오.

FutureTask가 2보다 2 인 경우 고려하십시오. [ListenableFuture][1].

다른 작업이 시작 되 자마자 여러 작업이 시작될 때 - "팬 아웃" - ListenableFuture는 작동합니다 : 요청 된 모든 콜백을 트리거합니다. 약간 더 많은 작업을 통해 우리는 할 수 있습니다."팬인, "또는 다른 여러 미래가 모두 끝나 자마자 청취 가능한 문제가 계산되도록 트리거됩니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top