2016-10-13 2 views
0

Um zu verstehen, wie Multi Threading funktioniert, verwende ich Queue und ReentrantLock, um Producer und Consumer Problem zu simulieren. Mein Producer-Thread fügt Daten in die Warteschlange ein, aber Consumer entfernt nicht. Ich bin mir nicht sicher, ob ich es richtig umgesetzt habe. Ich verstehe, dass dies bereits gestellt wurde, aber sie helfen nicht.Producer Consumer mit ReentrantLock und Queue

Paket Nebenläufigkeit;

import java.util.Queue; 
import java.util.concurrent.ArrayBlockingQueue; 
import java.util.concurrent.BlockingQueue; 
import java.util.concurrent.locks.Condition; 
import java.util.concurrent.locks.ReentrantLock; 


class Producer implements Runnable{ 
    Queue<Integer> list; 
    Condition con; 
    ReentrantLock lock; 
    int size; 


    Producer(Queue q1, Condition con, ReentrantLock l1,int size) 
    { 
     this.list=q1; 
     this.con=con; 
     this.lock=l1; 
     this.size=size; 
    } 

    public void run() 
    { 
     for(int i =0;i<20;i++) 
     { 
      if(lock.tryLock()) 
      { 
       while(list.size()==size) 
       { 
        try 
        { 
         con.await(); 
        } catch (InterruptedException e) { 
         // TODO Auto-generated catch block 
         e.printStackTrace(); 
        } 
       } 
       list.add(i); 
       System.out.println("Producer "+ Thread.currentThread() +"added "+i+" to the List"); 
       con.signalAll(); 
       lock.unlock(); 

      } 
     } 
    } 
} 


class Consumer implements Runnable{ 
    Queue<Integer> list; 
    Condition con; 
    ReentrantLock lock; 
    int size; 

    Consumer(Queue q1, Condition con, ReentrantLock l1,int size) 
    { 
     this.list=q1; 
     this.con=con; 
     this.lock=l1; 
     this.size=size; 
    } 

    public void run() 
    { 

     for(int innerLoop =0;innerLoop<20;innerLoop++){ 
      if(lock.tryLock()){ 
       while(list.size()<1){ 
        try { 
         con.await(); 
        } catch (InterruptedException e) { 
         // TODO Auto-generated catch block 
         e.printStackTrace(); 
        } 
       } 
       int i = (int) list.remove(); 
       System.out.println("Consumer "+ Thread.currentThread() +"removed "+i+" from the List"); 
       con.signalAll(); 
       lock.unlock(); 
      } 
     } 
    } 
} 

class SharedResource { 

    Queue list ; 

    Condition con; 
    ReentrantLock lock; 
    int size; 

    SharedResource() 
    { 
     size =20; 
     this.list=new LinkedList<Integer>(); 
     lock = new ReentrantLock(); 
     this.con = lock.newCondition(); 


    } 

    public Queue getList() { 
     return list; 
    } 

    public void setList(Queue list) { 
     this.list = list; 
    } 

    public Condition getCon() { 
     return con; 
    } 

    public void setCon(Condition con) { 
     this.con = con; 
    } 

    public ReentrantLock getLock() { 
     return lock; 
    } 

    public void setLock(ReentrantLock lock) { 
     this.lock = lock; 
    } 

    public int getSize() { 
     return size; 
    } 

    public void setSize(int size) { 
     this.size = size; 
    } 

} 

public class MYPRODUCERCONSUMER { 




    public static void main(String[] args) { 

     SharedResource producerCObj = new SharedResource(); 
     Producer producer= new Producer(producerCObj.getList(), producerCObj.getCon(), producerCObj.getLock(), producerCObj.getSize()); 
     Thread producerThread= new Thread(producer); 
     producerThread.start(); 

     Consumer consumer= new Consumer(producerCObj.getList(), producerCObj.getCon(), producerCObj.getLock(), producerCObj.getSize()); 
     Thread consumerThread= new Thread(consumer); 
     consumerThread.start(); 
    } 

} 
+0

Beginnen Sie mit der Erkenntnis, dass es keinen Sinn macht, hier zu sperren. ArrayBlockingQueue ist threadsicher und lässt Threads blockieren, wenn nichts für sie da ist. Sie können alle Sachen mit Sperren und Bedingungen löschen. –

+1

@Nathan Hughes Ich möchte verstehen, wie man mit Sperre und Bedingungen arbeiten, so dass ich ArrayBlockingQueue zu LinkedList geändert habe. – crazyStart

Antwort

1

In Ihrem Verbraucher versuchen Sie Sperre zu erhalten:

if(lock.tryLock()) 

Aber tryLock erwirbt das Schloss nur, wenn es nicht von einem anderen Thread zum Zeitpunkt des Aufrufs gehalten. Nur weil Sie den Produzenten zuerst starten, ist es sehr wahrscheinlich, dass er bereits vom Produzenten erworben wurde. Sie versuchen, unlock zu tun, aber nächste Anweisung ist tryLock (in einer Schleife), so gibt es keine Art von Ertrag für andere Thread. Mit anderen Worten: Consumer-Thread hat fast keine Chance, eine Sperre zu erhalten, weil der Producer-Thread sie wiedererlangt. Und nur weil Sie eine endliche Schleife haben (nur 20), ist Ihr Consumer gerade fertig.

Wenn Sie

class Producer implements Runnable{ 
Queue<Integer> list; 
Condition con; 
ReentrantLock lock; 
int size; 


    Producer(Queue q1, Condition con, ReentrantLock l1,int size) 
    { 
     this.list=q1; 
     this.con=con; 
     this.lock=l1; 
     this.size=size; 
    } 

    public void run() 
    { 
     for(int i =0;i<20;i++) 
     { 
      if(lock.tryLock()) 
      { 
       while(list.size()==size) 
       { 
        try 
        { 
         con.await(); 
        } catch (InterruptedException e) { 
         // TODO Auto-generated catch block 
         e.printStackTrace(); 
        } 
       } 
       list.add(i); 
       System.out.println("Producer "+ Thread.currentThread() +"added "+i+" to the List"); 
       con.signalAll(); 
       lock.unlock(); 

       try { 
        Thread.sleep(100); 
       } catch (InterruptedException e) { 
        e.printStackTrace(); 
       } 
      } 
     } 
    } 
} 

nach

lock.unlock(); 

in Ihrer Producer Schleife hinzufügen, werden Sie die Chance zu Consumer-Thread geben Sperre zu erhalten, und Sie werden wie erwartet erhalten führen.

+0

Ich habe versucht, Thread.sleep hinzuzufügen, aber mein Erzeuger-Thread wird nur ausgeführt. – crazyStart

+0

Ich habe die Antwort mit dem vollen Producer-Code bearbeitet. Versuchen Sie auch, die Schlafzeit zu erhöhen. Allerdings funktioniert es auf meinem Mac mit 10. –

Verwandte Themen