2017-05-13 6 views
1

저는 Java에 초보자이며 Java 동시성을 배우려고합니다. 나는 생산자 - 소비자 문제 (단일 생산자와 소비자)에 대한 간단한 코드를 작성했다. 데이터가 사용 가능할 때 소비자에게 알리지 않기 때문에 교착 상태가되는 것 같습니다. 누구든지 코드를 검토 할 수 있습니까?자물쇠 및 조건을 사용하여 Java에서이 제작자 - 소비자의 교착 상태가 발생하는 이유는 무엇입니까?

import java.util.List; 
import java.util.ArrayList; 
import java.util.concurrent.locks.*; 

class ThreadFactory implements Runnable{ 
    List<String> list = new ArrayList<>(); 
    Thread prThread; 
    final Lock lock = new ReentrantLock(); 
    final Condition notFull = lock.newCondition(); 
    final Condition notEmpty = lock.newCondition(); 
    final int CAPACITY = 10; 

    public enum Role{ 
    PRODUCER, 
    CONSUMER 
    }; 

    Role role; 
    public int i = 0; 

    private void produce() throws InterruptedException { 
     while(true){ 
      lock.lock(); 
      try{ 
       while(list.size() == CAPACITY){ 
        System.out.println("List is full to its CAPACITY, waiting"); 
        notEmpty.await(); 
       } 
       String str = "Data " + i++; 
       System.out.println("Putting " + str + " to list"); 
       list.add(str); 
       notFull.signalAll(); 
      } 
      finally{ 
       lock.unlock(); 
       Thread.sleep(500); 
      } 
     } 
    } 

    private void consume() throws InterruptedException{ 
     while(true){ 
      lock.lock(); 
      try{ 
       while(list.size() == 0){ 
        System.out.println("List is empty, waiting"); 
        notFull.await(); 
       } 
       String str = list.remove(list.size()-1); 
       System.out.println("Popping " + str + " from list"); 
       notEmpty.signal(); 
      } 
      finally{ 
       lock.unlock(); 
      } 
     } 
    } 

    public void run(){ 
     System.out.println("Starting thread " + prThread.getName()); 
     try{ 
      if(role == Role.PRODUCER){ 
       produce(); 
      }   
      else if(role == Role.CONSUMER){ 
       consume(); 
      } 
     } 
     catch(InterruptedException e){ 
      System.out.println("Thread interrupted"); 
     } 
    } 

    public ThreadFactory(List<String> l, int role, String name){ 
     this.list = l; 
     prThread = new Thread(this, name); 
     if(role == 0) 
      this.role = Role.PRODUCER; 
     else 
      this.role = Role.CONSUMER; 
     prThread.start(); 
    } 
} 

public class ProducerConsumer{ 
    public static void main(String[] args){ 
     List<String> l = new ArrayList<>(); 
     ThreadFactory c = new ThreadFactory(l,1, "Consumer"); 
     ThreadFactory p = new ThreadFactory(l,0, "Producer"); 
    } 
} 
+0

소비자 또는 제작자가 잠금을 획득하고 상태가 발생할 때까지 기다릴 때 잠금이 해제되지 않은 것으로 보입니다. 그래서 코드를 둘러 쌉니다 notEmpty.await(); 및 notFull.await(); lock.unlock() 및 lock.lock()에 의해. – Shinchan

+0

많은 제안에 감사드립니다. 이 문제는 @ Nathan이 말한 것과 동일합니다. 스레드는 자체 잠금 인스턴스를가집니다. 나는 자물쇠와 상태를 정적으로 만들었고 효과가 있었다. –

답변

1

이것은 교착 상태가 아닙니다. 잠금은 각 클래스의 인스턴스 멤버이며 각 실행 가능한 인스턴스는 자체 잠금을 만듭니다. 당신의 생산자와 소비자는 자기 소유의 자물쇠를 사용하여 서로의 신호를 보지 않고 영원히 기다립니다. 같은 잠금 장치를 사용해야합니다.

+0

대단히 감사합니다. 방금 잠김 및 조건 변수를 정적으로 만들고 모든 것이 작동했습니다. 많은 감사 :) –

-1

잘 실행되기 때문에, 나는 그것을 할 수 무슨 일이 일어나고 있는지 확실하지 않다 모두 )은 (소비 클래스의생산() 메소드 실행 (에서 방법)ThreadFactory.

내가 할 일은 Consumer 클래스와 Producer 클래스를 만들고 두 클래스 모두 Thread 클래스를 확장하는 것입니다. 그런 다음 각 클래스의 run()에서 consume() 및 producer()를 호출합니다.

import java.util.ArrayList; 
import java.util.List; 
import java.util.concurrent.locks.Condition; 
import java.util.concurrent.locks.Lock; 
import java.util.concurrent.locks.ReentrantLock; 

class ThreadFactory { 
    List<String> list = new ArrayList<>(); 
    final Lock lock = new ReentrantLock(); 
    final Condition notFull = lock.newCondition(); 
    final Condition notEmpty = lock.newCondition(); 
    final int CAPACITY = 10; 

    public int i = 0; 

    class Producer extends Thread { 

     @Override 
     public void run() { 
      try { 
       produce(); 
      } catch (InterruptedException e) { 
       e.printStackTrace(); 
      } 
     } 
    } 

    class Consumer extends Thread { 

     @Override 
     public void run() { 
      try { 
       consume(); 
      } catch (InterruptedException e) { 
       e.printStackTrace(); 
      } 
     } 
    } 

    private void produce() throws InterruptedException { 
     System.out.println("Starting thread " + Thread.currentThread().getName()); 
     while (true) { 
      lock.lock(); 
      try { 
       while (list.size() == CAPACITY) { 
        System.out.println("List is full to its CAPACITY, producer waiting"); 
        notFull.await(); 
       } 
       if (i == CAPACITY) i=0; 
       String str = "Data " + i++; 
       System.out.println("Putting " + str + " to list of size "+list.size()); 
       list.add(str); 
       if (list.size() ==1) 
        notEmpty.signal(); 
      } finally { 
       lock.unlock(); 
       Thread.sleep(500); 
      } 
     } 
    } 

    private void consume() throws InterruptedException { 
     System.out.println("Starting thread " + Thread.currentThread().getName()); 
     while (true) { 
      lock.lock(); 
      try { 
       while (list.size() == 0) { 
        System.out.println("List is empty, consumer waiting"); 
        notEmpty.await(); 
       } 
       String str = list.remove(list.size() - 1); 
       System.out.println("Popping " + str + " from list of size "+list.size()); 
       if (list.size() ==CAPACITY-1) 
        notFull.signal(); 
      } finally { 
       lock.unlock(); 
      } 
     } 
    } 

    public ThreadFactory(List<String> l){ 
     this.list = l; 
     Thread p= new Producer(); 
     p.setName("Producer"); 
     p.start(); 
     Thread c=new Consumer(); 
     c.setName("Consumer"); 
     c.start(); 
    } 
} 

public class ProducerConsumer { 
    public static void main(String[] args) { 
     List<String> l = new ArrayList<>(); 
     ThreadFactory pc = new ThreadFactory(l); 
    } 
} 

희망이 있습니다.