国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

一起學(xué)并發(fā)編程 - 利用觀察者模式監(jiān)聽線程狀態(tài)

Juven / 2468人閱讀

摘要:在前面的文章中介紹過觀察者模式及并發(fā)編程的基礎(chǔ)知識,為了讓大家更好的了解觀察者模式故而特意寫了這篇番外概述在多線程下我們需要知道當(dāng)前執(zhí)行線程的狀態(tài)是什么比如運(yùn)行,關(guān)閉,異常等狀態(tài)的通知,而且不僅僅是更新當(dāng)前頁面。

在前面的文章中介紹過 觀察者模式 及 并發(fā)編程的基礎(chǔ)知識,為了讓大家更好的了解觀察者模式故而特意寫了這篇番外..

概述

在Java多線程下,我們需要知道當(dāng)前執(zhí)行線程的狀態(tài)是什么比如運(yùn)行,關(guān)閉,異常等狀態(tài)的通知,而且不僅僅是更新當(dāng)前頁面。

觀察者模式: 是一種使用率極高的模式,用于建立一種對象與對象之間的依賴關(guān)系,一個(gè)對象發(fā)生改變時(shí)將自動(dòng)通知其他對象,其他對象將相應(yīng)作出反應(yīng)。在觀察者模式中,發(fā)生改變的對象稱為觀察目標(biāo),而被通知的對象稱為觀察者,一個(gè)觀察目標(biāo)可以對應(yīng)多個(gè)觀察者,而且這些觀察者之間可以沒有任何相互聯(lián)系,可以根據(jù)需要增加和刪除觀察者,使得系統(tǒng)更易于擴(kuò)展。

觀察者模式傳送門:http://blog.battcn.com/2017/12/11/java/design-pattern/observer-pattern/#more

案例

假設(shè)開發(fā)一個(gè)多線程爬蟲功能,由于數(shù)據(jù)過大需要利用多線程并行化來提升抓取的效率,并且在抓取過程中要記錄執(zhí)行線程的運(yùn)行狀態(tài)以便追溯問題原因

UML圖如下

1.定義具體觀察對象,實(shí)現(xiàn)JDK自帶的Observer接口,然后在需要實(shí)現(xiàn)的update方法中記錄下每個(gè)線程執(zhí)行的狀態(tài)信息

class ObserverListener implements Observer {
    /**
     * 避免多線程鎖競爭
     */
    private static final Object LOCK = new Object();

    @Override
    public void update(Observable observable, Object runnableEvent) {
        synchronized (LOCK) {
            ObservableRunnable.RunnableEvent event = (ObservableRunnable.RunnableEvent) runnableEvent;
            if (event != null) {
                if (event.getCause() != null) {
                    System.out.println("The Runnable [" + event.getThread().getName() + "] process failed and state is " + event.getState().name());
                    event.getCause().printStackTrace();
                } else {
                    System.out.println("The Runnable [" + event.getThread().getName() + "] data changed and state is " + event.getState().name());
                }
            }
        }
    }
}

2.定義具體被觀察的對象,該對象需要繼承Observable類,以及實(shí)現(xiàn)Runnable接口,這里run的實(shí)現(xiàn)非常簡單,執(zhí)行每一步驟操作時(shí)都進(jìn)行了通知,通知觀察者消息發(fā)生變更了

為什么每次都需要 setChanged

篩選有效通知,只有有效通知可以調(diào)用setChanged。比如,我的微信朋友圈一條狀態(tài),好友A點(diǎn)贊,后續(xù)該狀態(tài)的點(diǎn)贊和評論并不是每條都通知A,只有A的好友觸發(fā)的操作才會(huì)通知A。

便于撤銷通知操作,在主題中,我們可以設(shè)置很多次setChanged,但是在最后由于某種原因需要取消通知,我們可以使用clearChanged輕松解決問題。

主動(dòng)權(quán)控制,由于setChangedprotected,而notifyObservers方法為public,這就導(dǎo)致存在外部隨意調(diào)用notifyObservers的可能,但是外部無法調(diào)用setChanged,因此真正的控制權(quán)應(yīng)該在主題這里。

class ObservableRunnable extends Observable implements Runnable {

    /**
     * 線程名稱
     */
    private String name;

    ObservableRunnable(String name, ObserverListener listener) {
        this.name = name;
        // 將被觀察的對象注冊到觀察者中
        super.addObserver(listener);
    }

    /**
     * 發(fā)送通知
     *
     * @param event 通知的內(nèi)容
     */
    private void notifyChange(final RunnableEvent event) {
        // 前面說過 JDK自帶的 需要每次設(shè)置一次狀態(tài),代表當(dāng)前內(nèi)容更改了
        super.setChanged();
        super.notifyObservers(event);
    }

    @Override
    public void run() {
        try {
            notifyChange(new RunnableEvent(RunnableState.RUNNING, Thread.currentThread(), null));
            System.out.printf("根據(jù) [%s] 查詢 
", this.name);
            Thread.sleep(1000L);
            if (this.name.equals("T3")) {
                // 故意模擬報(bào)錯(cuò)
                throw new RuntimeException("故意拋出錯(cuò)誤");
            }
            notifyChange(new RunnableEvent(RunnableState.DOWN, Thread.currentThread(), null));
        } catch (Exception e) {
            notifyChange(new RunnableEvent(RunnableState.ERROR, Thread.currentThread(), e));
        }
    }

    enum RunnableState {
        /**
         * RUNNING:運(yùn)行
         * ERROR:異常
         * DOWN:正常結(jié)束
         */
        RUNNING, ERROR, DOWN
    }

    static class RunnableEvent {
        private final RunnableState state;
        private final Thread thread;
        private final Throwable cause;

        RunnableEvent(RunnableState state, Thread thread, Throwable cause) {
            this.state = state;
            this.thread = thread;
            this.cause = cause;
        }

        RunnableState getState() {
            return state;
        }

        public Thread getThread() {
            return thread;
        }

        Throwable getCause() {
            return cause;
        }
    }
}

3.創(chuàng)建測試工程

public class ObserverClient {

    public static void main(String[] args) {
        ObserverListener listener = new ObserverListener();
        List names = Arrays.asList("T1", "T2", "T3");
        for (String name : names) {
            Thread thread = new Thread(new ObservableRunnable(name, listener));
            thread.start();
        }
    }
}

4.運(yùn)行結(jié)果,通過運(yùn)行日志可以發(fā)現(xiàn),啟動(dòng)三個(gè)線程后同時(shí)執(zhí)行抓取操作,但是Thread-2線程在數(shù)據(jù)處理時(shí)發(fā)生了異常,在ObserverListener處也成功收到通知的內(nèi)容,然后對信息進(jìn)行了輸出操作。在實(shí)際過程中我們可以為異常進(jìn)行補(bǔ)償操作

The Runnable [Thread-1] data changed and state is RUNNING
The Runnable [Thread-0] data changed and state is RUNNING
根據(jù) [T1] 查詢 
The Runnable [Thread-2] data changed and state is RUNNING
根據(jù) [T2] 查詢 
根據(jù) [T3] 查詢 
java.lang.RuntimeException: 故意拋出錯(cuò)誤
The Runnable [Thread-0] data changed and state is DOWN
    at com.battcn.chapter14.ObservableRunnable.run(ObserverClient.java:67)
The Runnable [Thread-1] data changed and state is DOWN
    at java.lang.Thread.run(Thread.java:745)
The Runnable [Thread-2] process failed and state is ERROR
總結(jié)

本文,簡單講述了多線程環(huán)境下如何利用觀察者模式進(jìn)行線程狀態(tài)監(jiān)聽,也是對前面所講的基礎(chǔ)進(jìn)行鞏固,在學(xué)習(xí)的過程中,既要知其然也要知其所以然。這樣才能更好地駕馭它,更好地去理解和使用,也能更好地幫助我們觸類旁通

- 說點(diǎn)什么

全文代碼:https://gitee.com/battcn/battcn-concurent/tree/master/Chapter1-1/battcn-thread/src/main/java/com/battcn/chapter14

個(gè)人QQ:1837307557

battcn開源群(適合新手):391619659

微信公眾號:battcn(歡迎調(diào)戲)

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/70827.html

相關(guān)文章

  • 一起學(xué)并發(fā)編程 - 優(yōu)雅關(guān)閉

    摘要:文本將介紹兩種可以優(yōu)雅的終止線程的方式第一種在多線程模式中有一種叫兩步終止的模式可以優(yōu)雅的終止線程,這種模式采用了兩個(gè)步驟來終止線程,所以叫兩步終止模式。 Java中原來在Thread中提供了stop()方法來終止線程,但這個(gè)方法是不安全的,所以一般不建議使用。文本將介紹兩種可以優(yōu)雅的終止線程的方式... 第一種 在JAVA《Java多線程模式》中有一種叫Two-Phase Term...

    曹金海 評論0 收藏0
  • 一起學(xué)并發(fā)編程 - 簡易線程池實(shí)現(xiàn)

    摘要:并且,線程池在某些情況下還能動(dòng)態(tài)調(diào)整工作線程的數(shù)量,以平衡資源消耗和工作效率。同時(shí)線程池還提供了對池中工作線程進(jìn)行統(tǒng)一的管理的相關(guān)方法。 開發(fā)中經(jīng)常會(huì)遇到各種池(如:連接池,線程池),它們的作用就是為了提高性能及減少開銷,在JDK1.5以后的java.util.concurrent包中內(nèi)置了很多不同使用場景的線程池,為了更好的理解它們,自己手寫一個(gè)線程池,加深印象。 概述 1.什么是...

    Harriet666 評論0 收藏0
  • 一起學(xué)并發(fā)編程 - 等待與通知

    摘要:如果有其它線程調(diào)用了相同對象的方法,那么處于該對象的等待池中的線程就會(huì)全部進(jìn)入該對象的鎖池中,從新爭奪鎖的擁有權(quán)。 wait,notify 和 notifyAll,這些在多線程中被經(jīng)常用到的保留關(guān)鍵字,在實(shí)際開發(fā)的時(shí)候很多時(shí)候卻并沒有被大家重視,而本文則是對這些關(guān)鍵字的使用進(jìn)行描述。 存在即合理 在java中,每個(gè)對象都有兩個(gè)池,鎖池(monitor)和等待池(waitset),每個(gè)...

    Meathill 評論0 收藏0
  • 一起學(xué)并發(fā)編程 - Volatile關(guān)鍵字詳解

    摘要:比如用修飾的變量,就會(huì)確保變量在修改時(shí),其它線程是可見的。。多核環(huán)境中,多個(gè)線程分別在不同的中運(yùn)行,就意味著,多個(gè)線程都有可能將變量拷貝到當(dāng)前運(yùn)行的里。當(dāng)線程讀取變量時(shí),它將能看見被線程寫入的東西。 volatile是用來標(biāo)記一個(gè)JAVA變量存儲在主內(nèi)存(main memory)中,多線程讀寫volatile變量會(huì)先從高速緩存中讀取,但是寫入的時(shí)候會(huì)立即通過內(nèi)存總線刷到主存,同時(shí)內(nèi)存總...

    vpants 評論0 收藏0
  • java并發(fā)編程學(xué)習(xí)之Volatile

    摘要:但是的語義不足以確保遞增操作的原子性,在多線程的情況下,線程不一定是安全的。檢查某個(gè)狀態(tài)標(biāo)記,以判斷是否退出循環(huán)某個(gè)方法這邊和用普通的變量的區(qū)別是,在多線程的情況下,取到后,的值被改變了,判斷會(huì)不正確。 多線程為什么是不安全的 這邊簡單的講述一下,參考java并發(fā)編程學(xué)習(xí)之synchronize(一) 當(dāng)線程A和線程B同時(shí)進(jìn)入num = num + value; 線程A會(huì)把num的值...

    thekingisalwaysluc 評論0 收藏0

發(fā)表評論

0條評論

最新活動(dòng)
閱讀需要支付1元查看
<