2013-06-24 1 views
0

아래 코드에서 Thread t1이 Runnable 생성을 실행하고 Thread t2가 Runnable 실행을 실행하도록합니다. 이게 효과가 있니?2 개의 스레드에 대해 하나의 Runnable을 사용하여 하나가 생성되고 하나가 소비되도록 할 수 있습니까?

class Processor implements Runnable { 
    @override 
    run(){ 
     produce(); 
     consume(); 
    } 
    void produce(){ 
     // code to produce, synchronize 
    } 
    void consume(){ 
     // code to consume, synchronize 
    } 
} 

Class App { 
    public static void main(String[] args){ 
     Processor p = new Processor() 
     Thread t1 = new Thread(p); 
     t1.start(); 
     Thread t2 = new Thread(p); 
     t2.start(); 
    } 
} 
+3

시도하면 어떻게됩니까? run() 메소드의 절반만이 하나의 스레드에 의해 실행되고 나머지 절반은 두 번째 스레드에 의해 실행된다고 생각하게 만드는 요인은 무엇입니까? –

+0

디버그는 친구 –

+0

가능한 복제 http://stackoverflow.com/q/9562505/877472입니다. 그리고 다른 사람들이 말했듯이,'produce()'와'consume()'이 프로그램 흐름을 바꾸지 않고'run()'메소드에서 호출되고 있다면, 두 스레드는 똑같은 방식으로 동작 할 것입니다. –

답변

3

아래 코드에서 Runnable 생성을 실행하고 Thread t2를 사용하여 Runnable 실행을 원합니다.

첫 번째 대답은 당신이 이것을 원하지 않는다는 것입니다. 생성자 클래스와 소비자 클래스가 있어야합니다. 데이터를 잘 공유해야하지만 모듈화를 위해 제작자와 소비자 코드를 구분해야합니다. 예를 들어, 생산자 코드와 소비자 코드는 BlockingQueue을 공유 할 수 있으며 두 클래스에 전달되어 작업을 교환하는 데 사용됩니다.

코드가 현재 작성되었으므로 각 스레드는 분명히 produce()을 호출 한 다음 consume()을 호출 할 것입니다. 코드가 예제로 작성된 것으로 가정합니다.

동일한 클래스에서 생산자 코드와 소비자 코드를 실제로 결합하려는 경우, 일종의 부울 또는 다른 선택기를 전달하여 스레드에게 생산 또는 소비하도록 알릴 수 있습니다. 예를 들어

:

public class ProducerConsumerRunnable implements Runnable { 
     private final Processor processor; 
     private final boolean consume; 
     public ProducerConsumerRunnable(Processor processor, boolean consume) { 
      this.processor = processor; 
      this.consume = consume; 
     } 
     public void run() { 
      if (consume) { 
       processor.consume() 
      } else { 
       processor.produce() 
      } 
     } 
} 

그래서 당신은 같이 당신의 스레드를 시작할 것 :

Processor p = new Processor() 
Thread producerThread = new Thread(new ProducerConsumerRunnable(p, false)); 
producerThread.start(); 
Thread consumerThread = new Thread(new ProducerConsumerRunnable(p, true)); 
consumerThread.start(); 

편집 :

당신이 thread.start()를 호출해야 할 때 코드가 thread.run()를 호출 한 초기 . run()을 호출하면 foreground 스레드에서 실행 가능을 실행하는 반면 start()은 실제로 실행을 호출하는 백그라운드에서 스레드를 분기합니다.

+0

프로세서 자체를 변경하여 부울 값을 저장하는 대신 다른 클래스를 만든 이유가 있습니까? – Phoenix

+0

같은 'Processor' 인스턴스를 공유하고 싶다고 생각하는 것을 제외하고는 @Phoenix에 이유가 없습니다. – Gray

+0

예. 그래서 main 메소드에서 arrayblocking 큐를 생성하고 프로세서가 runnable을 구현하고 동일한 arrayblocking 큐에 클래스 변수 참조를 저장하고 동일한 프로세서를 두 개의 스레드에 전달할 수 있습니까? – Phoenix

0

아니요. 두 스레드 모두 생산 및 소비를 호출합니다.

두 개의 다른 실행 파일을 만들어야합니다. 하나는 생산 루틴 용이고 다른 하나는 소비 루틴 용입니다.

한 스레드가 생산 실행 가능을 실행하도록하고, 하나의 스레드가 실행 실행을 실행하도록하십시오.

0

이 작업을 수행하는 올바른 방법 :

class App { 
    public static void main(String[] args){ 
     Thread t1 = new Thread(){ 
      @Override run(){ 
       //insert produce method here 
      } 
     } 
     Thread t2 = new Thread(){ 
      @Override run(){ 
       //insert consume method here 
      } 
     } 
     t1.start(); // NOT run()! 
     t2.start(); 
    } 
} 

이 방법, 당신은 단지 App 클래스에 추가 할 수있는 두 개의 스레드 사이에 필요로하는 어떤 공유 변수.

또한 코드에서 지적했듯이 Thread.start()을 사용하면 Thread.run()이 아닌 새 스레드를 시작할 수 있습니다.

0

작성된 것처럼 두 스레드는 두 함수 호출을 수행합니다. 대부분 이런 상황에서, 아마도 produce() 및 consume() 함수를 다른 클래스에 두는 것이 가장 좋을 것입니다. 다른 많은 공유 논리가있는 경우 상속을 사용하여 공통 논리를 구현하는 공통 기본 클래스 (필요할 경우 추상화)에서 두 하위 클래스를 모두 분리합니다.

그들은 절대적으로, 긍정적으로

class Processor implements Runnable 
{ 
public Boolean producer; 
@override 
run() 
{ 
if(producer){ 
    produce(); 
} 
else{ 
    consume(); 
} 
} 
void produce() 
{ 
// code to produce, synchronize 
} 
void consume() 
{ 
// code to consume, synchronize 
} 
} 

같은 동일 (그들은 아마도하지 않음), 당신은 프로세서 클래스에 부울을 추가하는 시도 할 수 클래스, 무언가를 수 그리고 하나 거짓으로 producer을 설정해야하는 경우 , 그들을 실행하기 전에 다른에서 사실.