2014-07-16 2 views
3

동시에 실행하려면 내 프로그램에서 몇 가지 기능이 필요합니다. 이 프로세스는 레코드를 리턴합니다. 그러나 하나의 출력은 다른 출력으로의 입력입니다. 이런 경우, 함수 A가 함수 B에 어떤 레코드를 출력하는 데 약간의 시간이 걸리면 함수 A가이 프로세스의 입력으로 레코드를 제공 할 때까지 함수 B를 기다려야합니다. 대기, 조인 등과 같은 스레드 기능을 사용하여 간단하게이 작업을 수행 할 수 있습니까? 아니면 동일한 기능을 수행하는 다른 방법이 있습니까?자바에서 병렬 처리를위한 스레드 사용

편집 : 아래 제시된 제안에 따라 제작자 - 소비자 알고리즘을 BlockingQueue, ExecutorService, Future 및 CountDownLatch와 함께 사용하면 요청한 모든 기능을 얻을 수 있습니까?

+3

'java.util.concurrent' 패키지에서 클래스를 확인하십시오. – Stewart

+1

아주 간단한 작업이 있다면 플래그로 작동하는'volatile' 변수 만 있으면됩니다. 좀 더 복잡한 기능이 있다면 두 스레드가 사용하는 데이터에 대해'concurrent' 변수가 필요할 것입니다. Java 라이브러리에서 동시성을 구현할 수있는 방법이 많이 있으므로 거기에서 뭔가를 선택하십시오. – razvanz

답변

3

으로는 생산자 소비자와 차단 큐를 사용할 수 있습니다

또는

당신은 당신의 문제를 해결하기 위해 자바 동시성의 카운트 다운 래치를 사용할 수 있습니다.

CountDownLatch의 작동 방식은 무엇입니까?

// 지정된 카운트로 초기화 된 CountDownLatch를를 구축 :

CountDownLatch.java 클래스는 내부에 하나의 생성자가 정의합니다.

이 수는 본질적으로 래치가 대기해야하는 스레드의 수입니다. 이 값은 한 번만 설정할 수 있으며 CountDownLatch는이 수를 재설정 할 수있는 다른 메커니즘을 제공하지 않습니다.

CountDownLatch와의 첫 번째 상호 작용은 다른 스레드를 기다리는 goind 인 주 스레드와 관련이 있습니다. 이 주 스레드는 다른 스레드를 시작한 직후에 CountDownLatch.await() 메서드를 호출해야합니다. 실행은 시간까지 await() 메서드에서 멈추고 다른 스레드는 실행을 완료합니다.

다른 N 개의 스레드는 작업을 완료 한 CountDownLatch 개체에 알릴 필요가 있기 때문에 래치 개체에 대한 참조를 가져야합니다. 이 알림은 다음 방법으로 수행됩니다. CountDownLatch.countDown(); 메소드를 호출 할 때마다 생성자에서 설정된 초기 카운트가 1 씩 감소합니다. 따라서 N 개의 모든 스레드가이 메서드를 호출하면 count가 0에 도달하고 주 스레드는 await() 메서드를지나 실행을 다시 시작할 수 있습니다.

다음은 간단한 예입니다. Decrementer이 경우에

CountDownLatch, the waiting Waiter is released from the await() call. 
CountDownLatch latch = new CountDownLatch(3); 

Waiter  waiter  = new Waiter(latch); 
Decrementer decrementer = new Decrementer(latch); 

new Thread(waiter)  .start(); 
new Thread(decrementer).start(); 

Thread.sleep(4000); 

public class Waiter implements Runnable{ 

    CountDownLatch latch = null; 

    public Waiter(CountDownLatch latch) { 
     this.latch = latch; 
    } 

    public void run() { 
     try { 
      latch.await(); 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } 

     System.out.println("Waiter Released"); 
    } 
} 

public class Decrementer implements Runnable { 

    CountDownLatch latch = null; 

    public Decrementer(CountDownLatch latch) { 
     this.latch = latch; 
    } 

    public void run() { 

     try { 
      Thread.sleep(1000); 
      this.latch.countDown(); 

      Thread.sleep(1000); 
      this.latch.countDown(); 

      Thread.sleep(1000); 
      this.latch.countDown(); 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } 
    } 
} 

에 카운트 다운() 3 회 호출 한 후에는 해당 값을 전달하는 하나 개의 스레드에서 retrun 값을 얻을 필요가로 대신 실행 가능한 쓰레드를 생성하는 호출 할 수 있습니다 두 번째 스레드.

3

을 참조하십시오 I 동시 queuue 구현 중 하나를 제안 할 것입니다. 아마도 BlockingQueue, 즉 ArrayBlockingQueue 일 것입니다.

+0

+1. 예 ..'BlockingQueue'를 사용하는 것이 아마도 가장 간단한 해결책 일 것입니다. – TheLostMind

1

BlockingQueue 클래스와 생산자/소비자 패턴을 살펴보십시오.

첫 번째 스레드가 입력 블로킹 큐에서 작업 단위를 가져 와서 그 출력을 출력 블로킹 큐에 넣습니다 (크기 제한 포함). 두 번째 스레드가이 출력 대기열을 입력으로 사용하고 있습니다. 이 방법을 사용하면 스레드 수를 쉽게 조정할 수 있습니다.

작업 단위 당 작업 부하가 작지 않도록하십시오.

1

이것은 생산자 - 소비자 문제와 유사합니다. Java의 BlockingQueue을 사용할 수 있습니다.

프로세스 A는 결과를 대기열에 넣고 프로세스 B는 A의 출력이 대기열에서 준비 될 때까지 대기합니다. A의 출력이 이용 가능할 때, B는 그 출력을 읽고 소비 할 수있다.

1

이것은 소비자 생산자 문제와 같습니다. 다른 사람들이 제안한대로 BlockingQueue을 사용할 수 있습니다.

public static void main(final String[] args) { 
    final ExecutorService producer = Executors.newSingleThreadExecutor(); 
    final ExecutorService consumer = Executors.newSingleThreadExecutor(); 
    final BlockingQueue<Integer> workpieces = new LinkedBlockingQueue<>(); 

    producer.submit(new Runnable() { 

     @Override 
     public void run() { 
      final Random rand = new Random(); 

      for (;;) { 
       try { 
        workpieces.put(rand.nextInt()); 
        Thread.sleep(1000); 
       } catch (final InterruptedException e) { 
        Thread.currentThread().interrupt(); 
        return; 
       } 
      } 
     } 

    }); 

    consumer.submit(new Runnable() { 

     @Override 
     public void run() { 
      for (;;) { 
       try { 
        System.out.println("Got " + workpieces.take()); 
       } catch (final InterruptedException e) { 
        Thread.currentThread().interrupt(); 
        return; 
       } 
      } 
     } 

    }); 
} 

이는 소비자 스레드에 의해 인쇄되는 제조자 스레드 초마다 난수를 생성한다 : 여기서 사용하는 방법에 대한 예시이다.

1

생성자 스레드와 소비자 스레드간에 BlockingQueue를 사용할 수 있습니다. 생산자는 꽉 차 있지 않은 경우 결과를 대기열에 계속 추가하며 동시에 소비자 스레드는 대기열에서 보류중인 메시지를 처리 ​​할 수 ​​있습니다. 당신이 위에서 언급 한