java多線程之Thread-Per-Meaasge模式

一、Thread-Per-Meaasge模式

例如:上司把工作交給下屬:“能幫我打印一下這個文件嗎?”,想這樣的將工作委託給其他人的情況很常見,這個人把工作拜託給其他人後,就可以返回繼續做自己的工作了。

Thread-Per-Meaasge直譯過來就是“每個消息一個線程”的意思,Message可以理解爲命令、請求的意思,爲每個命令或請求分配一個線程,然後由這個線程來執行處理,這就是Thread-Per-Meaasge模式。

  • 提高響應性,縮短延遲時間。
  • 適用於操作順序沒有太高要求時。
  • 適用於不需要返回值時。
  • 應用於服務器。
  • 調用方法+啓動線程–>發送消息。

二、實例程序

我們來看一個使用Thread-Per-Message模式的實例程序,Main類委託Host類來顯示字符,Host類會創建並啓動一個線程,來處理該委託,啓動的線程使用Helper類來執行實際的顯示。

類名 說明
Main.java 向Host發送字符顯示請求的類
Host.java 針對請求創建的線程的類
Helper.java 提供字符顯示功能的被動類

實例程序的類圖:

img

1.Main類

package com.viagra.Thread_Per_Message_Pattern.Lesson1;

/**
 * @Auther: viagra
 * @Date: 2019/11/19 18:43
 * @Description:
 */
public class Main {
    /**
     * 先創建一個Host類的實例,然後調用Host的request方法。
     *
     * @param args
     */
    public static void main(String[] args) {
        System.out.println("Main -- BEGIN ");
        Host host = new Host();
        host.request(10, 'A');
        host.request(20, 'B');
        host.request(30, 'C');
        System.out.println("Main -- END ");
    }
}

2.Host類

package com.viagra.Thread_Per_Message_Pattern.Lesson1;

/**
 * @Auther: viagra
 * @Date: 2019/11/19 18:43
 * @Description:
 */
public class Host {
    /**
     * Host類的request方法新啓動了一個線程,實際操作將由該線程執行。
     * 使用java的匿名內部類來創建Thread的子類實例,並使用該實例來啓動線程。
     */
    private final Helper helper = new Helper();

    public void request(final int count, final char c) {
        System.out.println(" request( " + count + ", " + c + ") BEGIN");
        /**
         * 匿名內部類的run方法使用了request方法的參數count和c,
         * 當匿名內部類用到方法的參數或局部變量時,這些變量就必須聲明爲final,如果count和c不聲明爲final,程序會出現編譯錯誤。
         */
        new Thread() {
            public void run() {
                helper.handle(count, c);
            }
        }.start();
        System.out.println(" request( " + count + ", " + c + ") END");
    }
}

3.Helper類

package com.viagra.Thread_Per_Message_Pattern.Lesson1;

/**
 * @Auther: viagra
 * @Date: 2019/11/19 18:43
 * @Description:
 */
public class Helper {
    /**
     * 提供了一個用戶按指定次數顯示字符的handle方法,另外爲了延緩顯示速度,在slowly方法中使用了Thread.sleep方法。
     *
     * @param count
     * @param c
     */
    public void handle(int count, char c) {
        System.out.println(" handle (" + count + ", " + c + ") BEGIN");
        for (int i = 0; i < count; i++) {
            slowly();
            System.out.println(c);
        }
        System.out.println("~~~~~~~~~~~");
        System.out.println(" handle (" + count + ", " + c + ") END");
    }

    public void slowly() {
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

4.運行

Main -- BEGIN 
 request( 10, A) BEGIN
 request( 10, A) END
 request( 20, B) BEGIN
 handle (10, A) BEGIN
 request( 20, B) END
 handle (20, B) BEGIN
 request( 30, C) BEGIN
 request( 30, C) END
Main -- END 
 handle (30, C) BEGIN
A
B
C
A
B
C
A
B
C
A
B
C
A
B
C
A
B
C
A
C
B
A
B
C
A
B
C
A
~~~~~~~~~~~
 handle (10, A) END
C
B
C
B
B
C
C
B
B
C
C
B
C
B
B
C
B
C
C
B
C
B
~~~~~~~~~~~
 handle (20, B) END
C
C
C
C
C
C
C
C
C
C
~~~~~~~~~~~
 handle (30, C) END

5.實例程序的時序圖

img

6.實例程序的TimeThreads圖

img

如果Host類並不創建新的線程,而是由同一個線程來調用Helper類,則TimeThreads圖就應該如下圖所示:

img

三、Thread-Per-Message模式中的角色

1.Client(委託人)

Client角色會想Host發出請求request,但是並不知道Host角色是如何實現該請求的,在實例程序中,Main扮演該角色。

2.Host

Host收到Client的請求後,會新創建並啓動一個線程,新創建的線程將使用Helper角色來處理請求。如Host類。

3.Helper(助手)

Helper爲Host角色提供請求處理的功能,Host創建的新線程會利用Helper,如:Helper類。

img
代碼案例

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章