2016-10-13 10 views
0

マルチスレッドの仕組みを理解するために、キューとReentrantLockを使用してプロデューサとコンシューマの問題をシミュレートしています。私のプロデューサースレッドはキューにデータを追加していますが、コンシューマーは削除していません。私はそれを正しく実装しているかどうかはわかりません。私はこれがすでに尋ねられているが、彼らは助けていないと理解しています。ReentrantLockとキューを使用するコンシューマ

パッケージの同時実行性。

if(lock.tryLock()) 

しかしtryLockは、それが呼び出し時に別のスレッドによって保持されていないされている場合にのみ、ロックを取得:あなたの消費者に

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

ここからロックを解除する必要はありません。 ArrayBlockingQueueはスレッドセーフであり、スレッドが何もしないときにスレッドをブロックします。あなたはロックと条件ですべてのものを削除することができます。 –

+1

@Nathan Hughesロックや条件を扱う方法を理解したいので、ArrayBlockingQueueをLinkedListに変更しました。 – crazyStart

答えて

1

あなたがロックを取得してみてください。プロデューサーを最初に開始したからといって、プロデューサーが既にそれを取得している可能性が高いです。あなたはunlockをしようとしますが、次の命令はtryLock(ループ内)なので、他のスレッドのための歩留まりはありません。言い換えれば、コンシューマスレッドは、プロデューサスレッドがそれを再獲得するため、ロックを獲得する機会はほとんどありません。そして、ちょうどあなたが有限ループ(わずか20)を持っているので、コンシューマーはちょうど終了します。

あなたがプロデューサーループに

lock.unlock(); 

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(); 
       } 
      } 
     } 
    } 
} 

追加する場合は、ロックを取得するために消費者のスレッドにチャンスを与えるだろうと期待どおりの結果を取得します。

+0

私はThread.sleepを追加しようとしましたが、私のプロデューサスレッドはまだ実行するだけです。 – crazyStart

+0

フルプロデューサーコードで回答を編集しました。また、睡眠時間を増やしてみてください。しかし、私のMacでは10で動作します。 –

関連する問題