0

以下が保持されるプロデューサーコンシューマータイプのキューを設定する信頼できる方法があるかどうかは誰にも分かりますか?

1) プロデューサーは最初に 3 つのオブジェクトをキューに入れます

2) コンシューマーは 1 つのアイテムを消費し、2 つのオブジェクトをキューに残します

3) 制御はプロデューサーに戻り、プロデューサーはもう 1 つの項目を配置します - (今度は 3 つのオブジェクトが再びキューに置かれます)

4) 消費者はもう 1 つのアイテムを消費し、サイクルは継続します。

私が取り組んでいる課題のインターフェイスを使用せずに、ソリューションを手動で設定する必要があることに注意してください。アドバイスをいただければ幸いです。

このような微調整はスレッドで利用できますか?

4

4 に答える 4

3

私がおそらく行うことは、比較的平凡なキューを持ち、セマフォも持つことです。セマフォを -2 に初期化します。プロデューサがリクエストをエンキューするたびにセマフォをインクリメントするようにします。リクエストをデキューする前に、コンシューマにセマフォをデクリメントさせます。コンシューマーは、カウントが 1 になるまでデクリメントを行うことができないため、キューには常に 2 つの未処理の要求が存在します。

于 2012-11-24T05:23:50.753 に答える
1
I hope this solution gives you some help:

説明は次のとおりです。

2 つの別々のスレッド(Producer thread and Consumer thread)が、共通のキュー (ここでは配列について言及しました) で互いに連携して動作します。プロデューサーはデータ配列から 3 つの要素を配置し、コンシューマーは 1 つをフェッチして同じ配列から削除します。データ配列のすべての要素がキューに配置されると、コンシューマーは 1 つずつフェッチするだけです。put()およびtake()は、別のクラスで定義された同期メソッドDropです。

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;

public class ProducerConsumerExample {
    public static final Lock fileLock = new ReentrantLock();
    public static final Condition condition = fileLock.newCondition();
    public static String importantInfo[] = {
            "Mares eat oats",
            "Does eat oats",
            "Little lambs eat ivy",
            "A kid will eat ivy too",
            "abc",
            "def",
            "ghi",
            "jkl",
            "mno",
            "pqr"
    };
    public static List<String> list = new ArrayList<String>();
    public static boolean done = false;
    public static void main(String[] args) {
        Drop drop = new Drop();
        Thread tProducer = new Thread(new Producer(drop));
        Thread tConsumer = new Thread(new Consumer(drop));
        try{
        tProducer.start();
        tConsumer.start();
        }
        catch(Exception ie){}
    }
}

public class Consumer implements Runnable {
    private Drop drop;

    public Consumer(Drop drop) {
        this.drop = drop;
    }

    public void run() {
        try{
            ProducerConsumerExample.fileLock.lock();
            for (String message = drop.take();
                    ! message.equals("DONE");
                    message = drop.take()) {
                System.out.format("MESSAGE RECEIVED: %s%n", message);
                ProducerConsumerExample.list.remove(0);
                if(ProducerConsumerExample.done)
                    continue;
                else{
                    ProducerConsumerExample.condition.signal();
                    System.out.println("Consumer is waiting");
                    ProducerConsumerExample.condition.await();
                }
             } catch (InterruptedException e) {}
            }
        }
        catch(Exception e){

        }
        finally{
            ProducerConsumerExample.fileLock.unlock();
        }
    }
}
import java.util.Random;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class Producer implements Runnable {
    private Drop drop;
    public Producer(Drop drop) {
        this.drop = drop;
    }

    public void run() {
        try{
            ProducerConsumerExample.fileLock.lock();
            Random random = new Random();int check = 3;

            for (int i = 0;
                    i <ProducerConsumerExample.importantInfo.length;
                    i++) {
                if(i<check){
                System.out.println("Putting message");
                System.out.println(ProducerConsumerExample.importantInfo[i]);
                drop.put(ProducerConsumerExample.importantInfo[i]);
                }
                else{
                    check = check+3;
                    i--;
                    ProducerConsumerExample.condition.signal();
                    System.out.println("Producer is waiting");
                    ProducerConsumerExample.condition.await();
                }
            }
            drop.put("DONE");
            ProducerConsumerExample.done =true;
            ProducerConsumerExample.condition.signal();
            System.out.println("Producer is waiting");
            ProducerConsumerExample.condition.await();
        }
        catch(Exception e){
            e.printStackTrace();
        }
        finally{
            ProducerConsumerExample.fileLock.unlock();
        }
    }
}
import java.util.ArrayList;
import java.util.List;

public class Drop {
    // Message sent from producer
    // to consumer.
    private String message;
    public synchronized String take() {
        System.out.println(ProducerConsumerExample.list.size());
        return ProducerConsumerExample.list.get(0);
    }

    public synchronized void put(String message) {
        // Store message.
        ProducerConsumerExample.list.add(message);
    }
}
于 2014-06-12T13:31:46.540 に答える
0

     ArrayListを使用して、容量を3に設定できます。その後、プロデューサーが実行されるたびに、配列サイズがチェックされます。サイズが3未満の場合は、サイズが3になるまでArrayListに値を挿入するだけです。サイズが3の場合。notifyAll()メソッドを呼び出すだけで、順番を終了できます。
      同様に、コンシューマーの場合、サイズが3の場合、値の1つを消費し、それをArrayListから削除します。サイズが3未満の場合は、notifyAll()メソッドを呼び出して順番を終了します。
     これは基本的にそれが一言で言えばどのように機能するかです。実装は、それを使用して何を達成する予定かによって異なります。

     お役に立てれば。

于 2012-11-24T03:20:29.163 に答える
0

Java 7には、探しているもののように聞こえるLinkedTransferQueueがあります。または、親タイプのBlockingQueueを確認してください。そのうちの1つが法案に適合すると確信しています。

于 2012-11-24T03:14:49.837 に答える