1

セマフォを使用する必要がある生産者/消費者と同様の問題をコーディングする必要があります。私はいくつかの解決策を試しましたが、どれもうまくいきませんでした。最初にウィキペディアで解決策を試しましたが、うまくいきませんでした。私の現在のコードは次のようなものです。

コンシューマーのメソッド実行:

    public void run() {
    int i=0;
    DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
    String s = new String();
    while (1!=2){
        Date datainicio = new Date();
        String inicio=dateFormat.format(datainicio);
        try {
            Thread.sleep(1000);///10000
        } catch (InterruptedException e) {
            System.out.println("Excecao InterruptedException lancada.");
        }
        //this.encheBuffer.down();
        this.mutex.down();
        // RC
        i=0;
        while (i<buffer.length) {
            if (buffer[i] == null) {
                i++;
            } else {
                break;
            }
        }
        if (i<buffer.length) {
            QuantidadeBuffer.quantidade--;
            Date datafim = new Date();
            String fim=dateFormat.format(datafim);
            int identificador;
            identificador=buffer[i].getIdentificador()[0];
            s="Consumidor Thread: "+Thread.currentThread()+" Pedido: "+identificador+" Inicio: "+inicio+" Fim: "+fim+" posicao "+i;
            //System.out.println("Consumidor Thread: "+Thread.currentThread()+" Pedido: "+identificador+" Inicio: "+inicio+" Fim: "+fim+" posicao "+i);
            buffer[i]= null;
        }
        // RC
        this.mutex.up();
        //this.esvaziaBuffer.up();
        System.out.println(s);
  //            lock.up();
    }
}

プロデューサーのメソッド実行:

    public void run() {
    DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
    int i=0;
    while (1!=2){
        Date datainicio = new Date();
        String inicio=dateFormat.format(datainicio);
        // Produz Item
        try {
            Thread.sleep(500);//50000
        } catch (InterruptedException e) {
            System.out.println("Excecao InterruptedException lancada.");
        }
        //this.esvaziaBuffer.down();
        this.mutex.down();
        // RC
        i=0;
        while (i<buffer.length) {
            if (buffer[i]!=null) {
                i++;
            } else {
                break;
            }
        }
        if (i<buffer.length) {
            int identificador[]=new int[Pedido.getTamanho_identificador()];
            identificador[0]=i;
            buffer[i]=new Pedido();
            Produtor.buffer[i].setIdentificador(identificador);
            Produtor.buffer[i].setTexto("pacote de dados");
            QuantidadeBuffer.quantidade++;
            Date datafim = new Date();
            String fim=dateFormat.format(datafim);
            System.out.println("Produtor Thread: "+Thread.currentThread()+" Pedido: "+identificador[0]+" Inicio: "+inicio+" Fim: "+fim+" posicao "+i);
            i++;
        }
        // RC
        this.mutex.up();
        //this.encheBuffer.up();
    }
    //this.encheBuffer.up();
}

上記のコードでは、コンシューマースレッドが位置を読み取り、次に別のスレッドが同じ位置を読み取り、プロデューサーがその位置を埋めることはありませんでした。次のようになります。

Consumidor Thread: Thread[Thread-17,5,main] Pedido: 1 Inicio: 2011/11/27 17:23:33 Fim: 2011/11/27 17:23:34 posicao 1
Consumidor Thread: Thread[Thread-19,5,main] Pedido: 1 Inicio: 2011/11/27 17:23:33 Fim: 2011/11/27 17:23:34 posicao 1
4

4 に答える 4

9

セマフォではなくミューテックスを使用しているようですか?

ミューテックスを使用する場合、1 つのリソースをロックおよびロック解除するバイナリ同期しかありません。Sempahores には、シグナルまたは取得できる値があります。

バッファー全体をロック/ロック解除しようとしていますが、ご覧のとおり、プロデューサーまたはコンシューマーのいずれかがロックされ、リーダーがロックするとプロデューサーはバッファーを埋めることができないため、それは間違った方法です (最初にロックする必要があります)。

代わりに、セマフォを作成する必要があります。その後、プロデューサがデータの 1 つのパケットまたはブロックを書き込むときに、セマフォにシグナルを送ることができます。コンシューマーはセマフォの取得を試みることができるため、プロデューサーがパケットが書き込まれたことを通知するまで待機します。書き込まれたパケットを通知すると、コンシューマーの 1 つが起動され、1 つのパケットを読み取ることができることがわかります。パケットを読み取ってから、セマフォでの取得の試行に戻ることができます。その間にプロデューサが別のパケットを書き込んだ場合、再びシグナルを送信し、コンシューマのいずれかが別のパケットを読み続けます。等...

例えば:

(プロデューサー) - 1 つのパケットを書き込む - Semaphore.release(1)

(Consumer xN) - Semaphore.acquire(1) - 1 つのパケットを読み取る

複数のコンシューマーがある場合、コンシューマー(プロデューサーではない) は、競合状態を防ぐために、パケットを読み取るとき (ただし、セマフォを取得するときではない) にバッファーをロックする必要があります。以下の例では、すべてが同じ JVM 上にあるため、プロデューサーもリストをロックします。

import java.util.LinkedList;
import java.util.concurrent.Semaphore;

public class Semaphores {

    static Object LOCK = new Object();

    static LinkedList list = new LinkedList();
    static Semaphore sem = new Semaphore(0);
    static Semaphore mutex = new Semaphore(1);

    static class Consumer extends Thread {
        String name;
        public Consumer(String name) {
            this.name = name;
        }
        public void run() {
            try {

                while (true) {
                    sem.acquire(1);
                    mutex.acquire();
                    System.out.println("Consumer \""+name+"\" read: "+list.removeFirst());
                    mutex.release();
                }
            } catch (Exception x) {
                x.printStackTrace();
            }
        }
    }

    static class Producer extends Thread {
        public void run() {
            try {

                int N = 0;

                while (true) {
                    mutex.acquire();
                    list.add(new Integer(N++));
                    mutex.release();
                    sem.release(1);
                    Thread.sleep(500);
                }
            } catch (Exception x) {
                x.printStackTrace();
            }
        }
    }

    public static void main(String [] args) {
        new Producer().start();
        new Consumer("Alice").start();
        new Consumer("Bob").start();
    }
}
于 2011-11-27T22:26:09.963 に答える