Javaの並行プログラミングノート7

休止の保護同期モード

1.定義

実行結果の別のスレッドのスレッドの待機とそのガード付きサスペンション、

点数

  • 別のスレッドから結果を提供する必要性は、彼らがGuardedObjectは関連付けるようにということ、あります
  • あなたは今まであなたがメッセージキューを使用することができます別のスレッドに1つのスレッドに起因している場合は(プロデューサ/コンシューマを参照してください)
  • JDK、参加し、今後の実装の実現は、このモードが使用されています
  • 他の結果を待つので、同期モードに分類するため、

ここに画像を挿入説明

実装2

class GuardedObject {
    private Object response;
    private final Object lock = new Object();
    public Object get() {
        synchronized (lock) {
// 条件不满足则等待
            while (response == null) {
                try {
                    lock.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            return response;
        }
    }
    public void complete(Object response) {
        synchronized (lock) {
// 条件满足,通知等待线程
            this.response = response;
            lock.notifyAll();
        }
    }
}
  • アプリケーション
    スレッドが別のスレッドの結果を待ちます
    public static void main(String[] args) {
        GuardedObject guardedObject = new GuardedObject();
        new Thread(() -> {
            try {
			// 子线程执行下载
                List<String> response = download();
                log.debug("download complete...");
                guardedObject.complete(response);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }).start();
        log.debug("waiting...");
        // 主线程阻塞等待
        Object response = guardedObject.get();
        log.debug("get response: [{}] lines", ((List<String>) response).size());
    }

タイムアウトバージョン3. GuardedObjectは

class GuardedObjectV2 {
    private Object response;
    private final Object lock = new Object();
    public Object get(long millis) {
        synchronized (lock) {
            // 1) 记录最初时间
            long begin = System.currentTimeMillis();
            // 2) 已经经历的时间
            long timePassed = 0;
            while (response == null) {
             // 4) 假设 millis 是 1000,结果在 400 时唤醒了,那么还有 600 要等
                long waitTime = millis - timePassed;
                log.debug("waitTime: {}", waitTime);
                if (waitTime <= 0) {
                    log.debug("break...");
                    break;
                }
                try {
                    lock.wait(waitTime);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                // 3) 如果提前被唤醒,这时已经经历的时间假设为 400
                timePassed = System.currentTimeMillis() - begin;
                log.debug("timePassed: {}, object is null {}",
                        timePassed, response == null);
            }
            return response;
        }
    }
    public void complete(Object response) {
        synchronized (lock) {
            // 条件满足,通知等待线程
            this.response = response;
            log.debug("notify...");
            lock.notifyAll();
        }
    }
}

テスト、タイムアウトなし

    public static void main(String[] args) {
        GuardedObjectV2 v2 = new GuardedObjectV2();
        new Thread(() -> {
            sleep(1);
            v2.complete(null);
            sleep(1);
            v2.complete(Arrays.asList("a", "b", "c"));
        }).start();
        Object response = v2.get(2500);
        if (response != null) {
            log.debug("get response: [{}] lines", ((List<String>) response).size());
        } else {
            log.debug("can't get response");
        }
    }

輸出

08:49:39.917 [main] c.GuardedObjectV2 - waitTime: 2500
08:49:40.917 [Thread-0] c.GuardedObjectV2 - notify...
08:49:40.917 [main] c.GuardedObjectV2 - timePassed: 1003, object is null true
08:49:40.917 [main] c.GuardedObjectV2 - waitTime: 1497
08:49:41.918 [Thread-0] c.GuardedObjectV2 - notify...
08:49:41.918 [main] c.GuardedObjectV2 - timePassed: 2004, object is null false
08:49:41.918 [main] c.TestGuardedObjectV2 - get response: [3] lines

原理に参加

呼び出し側は生きているスレッドの状態を確認するためのポーリングしています

t1.join();これは、次のコードと同等です

synchronized (t1) {
 // 调用者线程进入 t1 的 waitSet 等待, 直到 t1 运行结束
 while (t1.isAlive()) {
 t1.wait(0);
 }
}

4.マルチタスキングバージョンGuardedObjectは

図先物住宅メールボックスのような層(メールボックスの各部屋番号を持っている)、メッセージを待っているような左T0、T2、T4集団、及び右
サイドは、T1、T3、T5郵便配達のようなものである
複数で必要に応じてパラメータとして渡されたクラスGuardedObjectはオブジェクト間の使用ではなく、非常に便利なので、中産階級のためのデカップリングに設計されている
そうではない人だけが、[結果]をデカップリング待っていることを[結果]は生産者が、同時に複数のタスクをサポートすることができます管理
ここに画像を挿入説明
新しいIDガード付きオブジェクトを識別するために使用される、それGuardedObjectは()クラスのもう一つのID。

デカップリングの中間クラス


class Mailboxes {
    private static Map<Integer, GuardedObject> boxes = new Hashtable<>();
    private static int id = 1;
    // 产生唯一 id
    private static synchronized int generateId() {
        return id++;
    }
    public static GuardedObject getGuardedObject(int id) {
        return boxes.remove(id);
    }
    public static GuardedObject createGuardedObject() {
        GuardedObject go = new GuardedObject(generateId());
        boxes.put(go.getId(), go);
        return go;
    }
    public static Set<Integer> getIds() {
        return boxes.keySet();
    }
}

公開された93元の記事 ウォン称賛31 ビュー30000 +

おすすめ

転載: blog.csdn.net/weixin_43866567/article/details/104975596