マルチスレッド・ノート5待ちキューをブロックする通知

オブジェクトO =新しい新しいオブジェクト();
o.wait();
o.notify();
o.notifyAll();
waitメソッドと通知オブジェクト属しメソッドを( "通知"を意味します)。

スレッドはo.wait()を呼び出すと、Aが自動的にCPU状態から解放され、待機中のRunnable状態となるであろう、O指向オブジェクトセットを待って、Aは、待機セットに転送されます。

Bスレッドの呼び出しがo.notifyとき();ときにランダムセットに待機しているスレッドが、o.notifyAll()を起動します。それはすべてのスレッド、B自体には全く影響を覚ますでしょう。

3上記の方法は、上記の方法を使用する前に、予め定められたように、変更されたオブジェクトを生成するために待機するように設定されているため、ロックされなければなりません。
同期(O){
o.wait()//内部アンロックロック、ウェイクアップ時にスレッドCPUを放棄する前に待機する
}再びロックされる//要求を、そして実行UNLOCKは、
(O){同期
o.notify( )
}
ここに画像を挿入説明

import java.util.Scanner;

/*
单生产者-单消费者情况

1. 是不是线程安全的?   是否有共享,是否有修改?
2. 怎么修改成线程安全的版本? 通过加锁解决
                              volatile 不可以解决问题
3. 生产者在队列满时等待-消费者在队列空时等待
4. 生产者需要唤醒可能在等消费者;消费者需要唤醒可能在等的生产者
*/
public class MyBlockingArrayQueue {
    int[] array = new int[10];  // 下标处的数据可能出现生产者和消费者修改同一处的情况
    int front = 0;  // 只有消费者修改 front
    int rear = 0;   // 只有生产者修改 rear
    int size = 0;   // size 是生产者消费者都会修改的

    // 生产者才会调用 put
    synchronized void put(int value) throws InterruptedException {
        // 考虑满的情况
        if (size == array.length) {
            // 队列已满
            //throw new RuntimeException("队列已满"); //满了
            wait(); //停
        }

        array[rear] = value;
        rear++;
        if (rear == array.length) {
            rear = 0;
        }
        //rear = (rear + 1) % array.length;
        size++;     // 我们需要保障的是 size++ 的原子性,所以 volatile 无法解决
        notify();
    }

    // 调用 take 的一定是消费者
    synchronized int take() throws InterruptedException {
        // 考虑空的情况
        if (size == 0) {
            // 空的
            //throw new RuntimeException("队列已空");
            wait();
        }

        int value = array[front];
        front++;
        if (front == array.length) {
            front = 0;
        }
        //front = (front + 1) % array.length;
        size--;
        notify();

        return value;
    }

    static MyBlockingArrayQueue queue = new MyBlockingArrayQueue();

    static class Producer extends Thread {
        @Override
        public void run() {
            try {
                for (int i = 0; i < 100; i++) {
                    System.out.println("准备放入 " + i);
                    queue.put(i);
                    System.out.println("放入成功");
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) throws InterruptedException {
        Producer producer = new Producer();
        producer.start(); //生产者启动

        Thread.sleep(2 * 1000);

        Scanner scanner = new Scanner(System.in);//消费者手动控制
        while (true) {
            scanner.nextLine();
            System.out.println(queue.take());
        }
    }
}

これは、そのプラスを確保するために時間がかかりません、プラス取ることができないときsynchornized。
テイク、置く方法、で待ち、それが別のスレッドが対応するメソッドの終わり目を覚ますために通知を呼び出しを待つために、何の時空、スレッドの待機を取らない、ブロッキングが、増加が満杯にないことを確認することで、通知します。

、プロデューサーのウェイクプロデューサーを表示されることがあり、消費者はこの時点では、消費者の状況を覚ますときに多くの多くの待機スレッドが条件を決定するために再び目を覚ますにはサイズのランダムな変動は、解決策があるので、スレッドセーフにつながるだろう、一方、交換した場合それは、です。

多くはので、すべての生産者がでもあること、(消費者がCPUをつかむとき、キューが空になっている)すべての消費者が待機中であるということです、そして、キュー内の生産者がウェイク生産を埋めるために場面の多くの種類にあります。プログラム全体が停止した原因と、待ってください。解決策は、変更のnotifyAllを通知することです。

キュー表の実装遮断するためArrayBlockingQueueでJava
LinkedBlockingQueueリストの実装
実装PriorityBlockingQueueスタックを

公開された15元の記事 ウォンの賞賛0 ビュー260

おすすめ

転載: blog.csdn.net/rushrush1/article/details/104878573