マルチスレッド設計パターン - 保護サスペンド モード

待機および通知メソッドを使用して実装

このようなシナリオがあります。2 つのスレッドがあり、そのうちの 1 つは他のスレッドの実行結果を待つ必要があります。その後、join メソッドを使用してそれを達成できますが、今は jon を使用してそれを達成していません。

package com.dongmu.test;

/**
 * 多线程设计宝石之保护性暂停模式
 *
 * 这个设计模式相对于join方法有什么好处呢?
 * 1:我们在工作线程结束之后还可以执行其他的操作,而join方法只能等待工作的线程执行结束之后才嫩返回
 * 结果让主线程继续运行。
 * 2:我们这里等待结果的变量是局部的而不是全局的。
 */
public class Test19 {
    
    


    public static void main(String[] args) {
    
    
        GuardedObject guardedObject = new GuardedObject();

        new Thread(()->{
    
    
            Object o = guardedObject.get();
            System.out.println("等待获取数据成功");
        },"t1").start();

        try {
    
    
            Thread.sleep(2000);
        } catch (InterruptedException e) {
    
    
            throw new RuntimeException(e);
        }

        new Thread(()->{
    
    
            guardedObject.cmplete();
        },"t2").start();
    }



}

class GuardedObject{
    
    
//    需要获取的结果
    private Object response;

    private Object lock = new Object();

    public Object get(){
    
    
        synchronized (lock){
    
    
            while (response==null){
    
    
                try {
    
    
                    lock.wait();
                } catch (InterruptedException e) {
    
    
                    e.printStackTrace();
                }
            }
            return response;
        }
    }


    public void cmplete(){
    
    
        synchronized (lock){
    
    
            response = new Object();
            lock.notifyAll();
        }
    }
}

タイムアウトを設定できる get メソッド

public Object get(long timeout){
    
    
        long now = System.currentTimeMillis();

        long passtime = 0;

        synchronized (lock){
    
    
            while (response==null){
    
    
                if (passtime>=timeout) break;
                try {
    
    
//                    这里这么写是为了避免虚假唤醒的问题。也就是调用complete方法传递null值
                    lock.wait(timeout-passtime);
                } catch (InterruptedException e) {
    
    
                    e.printStackTrace();
                }
                passtime = System.currentTimeMillis() - now;
            }
            return response;
        }
    }

同時に、タイムアウト待機を使用する join メソッドの基本的な実装原理を確認することもできます. 上で書いたのは、結合タイムアウト待機の実装原理です.

public final synchronized void join(long millis)
    throws InterruptedException {
    
    
        long base = System.currentTimeMillis();
        long now = 0;

        if (millis < 0) {
    
    
            throw new IllegalArgumentException("timeout value is negative");
        }

        if (millis == 0) {
    
    
            while (isAlive()) {
    
    
                wait(0);
            }
        } else {
    
    
            while (isAlive()) {
    
    
                long delay = millis - now;
                if (delay <= 0) {
    
    
                    break;
                }
                wait(delay);
                now = System.currentTimeMillis() - base;
            }
        }
    }

上記はすべてシングルタスクのケースですが、上記のコードをマルチタスク バージョンに変更することもできます。

マルチタスク版

次のコードを GuradeObject クラスに追加します。

    private int id;

    public int getId() {
    
    
        return id;
    }

    public void setId(int id) {
    
    
        this.id = id;
    }

    public GuardedObject(int id) {
    
    
        this.id = id;
    }

そして、GuardedObject クラスを格納するパブリック クラスを作成します。


/*
这个MailBox是一个通用类,而上面的Postman和people都是和业务相关的代码,以后可以根据业务逻辑来实现
 */
class MailBox{
    
    
    private static Map<Integer,GuardedObject> map = new ConcurrentHashMap<>();

    private static int id = 1;

    private static synchronized int  getId(){
    
    
        return id++;
    }

    public static GuardedObject getGuardedObject(int id){
    
    
        return map.remove(id);
    }

    public static GuardedObject createGurdeObject (){
    
    
        GuardedObject guardedObject = new GuardedObject(getId());
        map.put(guardedObject.getId(),guardedObject);
        return guardedObject;
    }

    public static Set<Integer> getIds(){
    
    
        return map.keySet();
    }

}

同時に業務クラスの作成、タスクの追加、実行結果の取得をそれぞれ行う


class People extends Thread{
    
    
    @Override
    public void run() {
    
    
        GuardedObject gurdeObject = MailBox.createGurdeObject();
        System.out.println("线程id"+gurdeObject.getId()+"   开始接收内容");
        Object o = gurdeObject.get();
        System.out.println("线程id"+gurdeObject.getId()+",获取到内容:"+o);
    }
}

class PostMan extends Thread{
    
    
    private int id;

    public PostMan( int id) {
    
    
        this.id = id;
    }

    @Override
    public void run() {
    
    
        GuardedObject guardedObject = MailBox.getGuardedObject(id);
        guardedObject.cmplete("线程:"+id);
    }
}

最後にテストするコードを書く

for (int i = 0; i < 3; i++) {
    
    
            new People().start();
        }

        Thread.sleep(2000);

        for (Integer id : MailBox.getIds()) {
    
    
            new PostMan(id).start();
        }

時間

おすすめ

転載: blog.csdn.net/qq_45401910/article/details/128411623