2011-11-08 2 views
2

자바 스레드에 대한 기본적인 질문을하고 싶습니다. 생산자 - 소비자 시나리오를 생각해 봅시다. 한 명의 생산자와 n 명의 소비자가 있다고 가정 해보십시오. 소비자는 임의의 시간에 도착하고 일단 제공되면 사라집니다. 즉, 각 소비자는 자체 스레드에서 실행됩니다. 소비자를위한 영원한 조건을 계속 사용해야합니까?Java - Basic Multithreading

public class Consumer extends Thread { 
    public void run() { 
     while (true) { 
     } 
    } 
} 

스레드가 계속 실행되지 않습니까? 그것은 것

+0

잘 모르겠습니다. 이 스레드는 실제로 영원히 실행됩니다. 영원한 달리기를 사용할지 말지는 완전히 당신에게 달려 있습니다. – alf

답변

1

, 당신은

while(beingServed) 
{ 
    //check if the customer is done being served (set beingServed to false) 
} 

처럼이 죽을 의미 때 당신이 루프를 탈출거야 이런 식으로 뭔가 작업을 수행 할 수 있습니다 있도록.

1

소비자의 존재를 나타내는 boolean을 사용하지 않는 이유는 무엇입니까?

public class Consumer extends Thread { 
    private volatile boolean present; 

    public Consumer() { 
     present = true; 
    } 

    public void run() { 
     while (present) { 
      // Do Stuff 
     } 
    } 

    public void consumerLeft() { 
     present = false; 
    } 
} 
+1

선물은 휘발성이어야합니다. ;) –

+0

@PeterLawrey 뭔가를 잊어 버린 것을 알았습니다 : P –

3

스레드를 확장하지 않고 대신 Runnable을 구현합니다.

스레드가 영원히 돌아 오려면 영원히 반복해야합니다. (- 즉, 결코 당신이 스레드의 새로운 종류를 코딩하지 않는 한)

일반적인 대안은 그것은 스레드를 확장 에 좋은 생각이 아니다

while(!Thread.currentThread().isInterrupted()) { 

또는

while(!Thread.interrupted()) { 
+0

다른 스레드 (서비스되지 않은 소비자)가 일찍 죽지 않을 것이라고 보장합니까? –

+0

하나의 스레드가 다른 스레드를 멈추게하는 것은 단지 발생하는 것이 아닙니다. 실제로 그렇게 간단하지 않은 무언가. 왜 다른 스레드가 죽을지도 모른다는 이유를 설명 할 수 있습니까? –

+1

당신이 물어 주어서 기쁩니다. 나는 그 문제에 대해 자바와 OOP에 처음 온 사람이다. 주어진 시간에 5 명의 소비자가 있고, 그들은 생산자에 의해 봉사되기를 기다리고 있습니다. 따라서 5 개의 소비자 스레드가 분명히있을 것입니다. Thread.interrupted()는 정적 메소드이기 때문에 하나의 쓰레드가 인터럽트를하면 다른 쓰레드도 모두 죽게됩니까? –

0

을 사용하는 것입니다 .

가장 좋은 방법은 다음과 같이, 스레드의 생성자에 Runnable를 전달하는 것입니다 : 일반적으로

public class Consumer implements Runnable { 

    public void run() { 
     while (true) { 
      // Do something 
     } 
    } 
} 

new Thread(new Consumer()).start(); 

, while(true)는 OK,하지만 당신은 정상 wake 또는 가짜 웨이크 업으로하거나, 중단되고 처리해야 . 웹에는 많은 예제가 있습니다.

나는 Java Concurrency in Practice을 읽는 것이 좋습니다.

+0

깨어남이란 무엇입니까? 그리고 가짜 웨이크 업을 어떻게 유발합니까? 정의에 의해 코드에 기인 한 웨이크 업이 아닌가? –

0

생산자 - 소비자 패턴에 대해 더 잘 wait() 및 notify()를 사용하십시오. 이 부분은 tutorial입니다. while (true) 루프를 사용하는 것보다 훨씬 효율적입니다.

+0

BlockingQueue를 사용하는 것이 더 쉽고 간단합니다. –

0

while (true) 내에서 스레드를 죽이거나 죽이기 전까지 스레드가 메시지를 처리하도록하려면 생성자 스레드 (또는 SynchronizedQueue 또는 큐 시스템)에 대한 동기화 호출이 있습니다. 메시지를 사용할 수있게됩니다. 메시지가 소비되면 루프가 다시 시작되고 다시 대기합니다.

생산자가 보낸 메시지를 한 번만 가져온 스레드를 수동으로 인스턴스화하려면 while (true)을 사용하지 마십시오.

1

먼저 각 소비자에 대해 만들고 소비자가 작업을 마친 후에는 소비자가 실행 기능을 끝내고 죽을 것이므로 무한 루프가 필요 없습니다. 그러나 각 소비자에 대한 스레드를 만드는 것은 좋은 생각이 아닙니다. 스레드 생성은 성능 관점에서 상당히 비싸기 때문입니다. 스레드는 매우 고가의 자원입니다. 또한, 나는 runnable을 구현하고 스레드를 확장하지 않는 것이 더 낫다는 위의 대답에 동의한다.스레드를 사용자 정의하려는 경우에만 스레드를 확장하십시오. 스레드 풀을 사용하고 소비자가 스레드 풀에서 스레드가 실행 한 실행 가능 개체가 될 것을 강력히 제안합니다. 코드는 다음과 같아야합니다.

public class ConsumerMgr{ 

int poolSize = 2; 

int maxPoolSize = 2; 

long keepAliveTime = 10; 

ThreadPoolExecutor threadPool = null; 

final ArrayBlockingQueue<Runnable> queue = new ArrayBlockingQueue<Runnable>(
     5); 

public ConsumerMgr() 
{ 
    threadPool = new ThreadPoolExecutor(poolSize, maxPoolSize, 
      keepAliveTime, TimeUnit.SECONDS, queue); 

} 

public void runTask(Runnable task) 
{ 
    // System.out.println("Task count.."+threadPool.getTaskCount()); 
    // System.out.println("Queue Size before assigning the 
    // task.."+queue.size()); 
    threadPool.execute(task); 
    // System.out.println("Queue Size after assigning the 
    // task.."+queue.size()); 
    // System.out.println("Pool Size after assigning the 
    // task.."+threadPool.getActiveCount()); 
    // System.out.println("Task count.."+threadPool.getTaskCount()); 
    System.out.println("Task count.." + queue.size()); 

}