使用觀察者模式實現線程將計算結果回調給多個對象__java_concurrency

來源:互聯網
上載者:User

《Java網路編程》第三章線程講使用回調的方法從線程中返回資訊給對象。例如,如果有多個對象對線程的計算結果感興趣,那麼線程可以儲存一個要回調的對象列表。特定的對象可以通過調用線程類的一個方法把自己添加到這個列表中來完成註冊,表示自己對計算結果高度興趣。如果有多個類的執行個體對結果感興趣,可以定義一個新的Observer interface (介面),所有這些類都要實現這個新介面。這個Observer interface(介面)將聲明回調方法。以上是觀察者模式的典型應用情境。

接下來將上面的需求實現。

1.       Observer介面

聲明回調方法update

interface Observer {    void update(byte[] digest);}
2.       感興趣的觀察者InstanceCallbackDigestUserInterface01

其中將通知者作為其成員變數

public class InstanceCallbackDigestUserInterface01 implements Observer {    static Logger logger = LoggerFactory.getLogger(InstanceCallbackDigestUserInterface01.class);    private String filename;    private byte[] digest;    public InstanceCallbackDigestUserInterface01(String filename) {        this.filename = filename;    }    @Override    public String toString() {        String result = filename + ": ";        if (digest != null) {            result += DatatypeConverter.printHexBinary(digest);        } else {            result += "digest not available";        }        return result;    }    @Override    public void update(byte[] digest) {        this.digest = digest;        //只是顯示摘要,但功能更強的類還可以完成其他動作        //如將摘要儲存在一個欄位中,用它啟動另一個錢程,或者對它完成進一步的計算。        logger.info(this.toString());    }}
3.       感興趣的觀察者InstanceCallbackDigestUserInterface02以及新線程任務SaveDatabase
public class InstanceCallbackDigestUserInterface02 implements Observer {    Logger logger = LoggerFactory.getLogger(InstanceCallbackDigestUserInterface02.class);    byte[] digest = null;    @Override    public void update(byte[] digest) {        logger.info("interface02 get this digest");        this.digest = digest;        ExecutorService exec = Executors.newCachedThreadPool();        exec.submit(new SaveDatabase(digest));    }}class SaveDatabase implements Runnable {    Logger logger = LoggerFactory.getLogger(SaveDatabase.class);    private byte[] digest;    public SaveDatabase(byte[] digest){        this.digest = digest;    }    @Override    public void run() {        String s = DatatypeConverter.printHexBinary(digest);        logger.info(s);    }}
4.       通知者InstanceCallbackDigest

儲存一個要回調的對象列表callback。特定的對象可以通過調用attach方法把自己添加到這個列表中來完成註冊

public class InstanceCallbackDigest implements Runnable {    Logger logger = LoggerFactory.getLogger(InstanceCallbackDigest.class);    private String filename;    private LinkedHashSet<Observer> callback = new LinkedHashSet<>();    public InstanceCallbackDigest(String filename) {        this.filename = filename;    }    public void attach(Observer observer) {        callback.add(observer);    }    public void detach(Observer observer) {        callback.remove(observer);    }    @Override    public void run() {        try {            FileInputStream in = new FileInputStream(filename);            MessageDigest sha = MessageDigest.getInstance("SHA-256");            DigestInputStream din = new DigestInputStream(in, sha);            while (din.read() != -1) ;  // read entire file            din.close();            byte[] digest = sha.digest();            for (Observer o:callback                 ) {                logger.info("callback update");                o.update(digest);            }        } catch (IOException | NoSuchAlgorithmException ex) {            System.err.println(ex);        }    }}
5.       Test類
public class Test {    static Logger logger = LoggerFactory.getLogger(Test.class);    public void calculateDigest(String filename, LinkedHashSet<Observer> callback) {        InstanceCallbackDigest cb = new InstanceCallbackDigest(filename);        //註冊        for (Observer o : callback                ) {            cb.attach(o);        }        Thread t = new Thread(cb);        t.start();    }    @org.junit.Test    public void test () {        logger.info("main線程");        String[] strs = new String[]{"bw01.txt","pom.xml"};//        String[] strs = new String[]{"bw01.txt"};        for (String filename : strs) {            //註冊            InstanceCallbackDigestUserInterface01 d = new InstanceCallbackDigestUserInterface01(filename);            InstanceCallbackDigestUserInterface02 interface02 = new                    InstanceCallbackDigestUserInterface02();            LinkedHashSet<Observer> callback = new LinkedHashSet<>();            callback.add(d);            callback.add(interface02);            //啟動了線程            calculateDigest(filename, callback);            //如何通知主線程子線程結束?            try {                TimeUnit.SECONDS.sleep(3l);            } catch (InterruptedException e) {                e.printStackTrace();            }        }    }}
6.       類圖


7.       運行結果

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.