《图解Java多线程设计模式》之八:Thread-Per-Message模式

一,Thread-Per-Message模式

翻译过来就是 每个消息一个线程。message可以理解为命令,请求。为每一个请求新分配一个线程,由这个线程来执行处理。
Thread-Per-Message模式中,请求的委托端和请求的执行端是不同的线程,请求的委托端会告诉请求的执行端线程:这项工作就交给你了

二,示例程序

Host类:针对请求创建线程的类
Helper类:执行端,实际进行请求的处理

代码:

public class Helper {

    public void handle(int count, char c){
        System.out.println("     handle("+count+" , "+c+") begin");
        for (int i = 0; i < count; i++) {
            slowly();
            System.out.print(c);
        }
        System.out.println("");
        System.out.println("     handle("+count+" , "+c +") end");
    }

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

        }
    }
}
public class Host {
    private final Helper helper = new Helper();

    /**
     * requst方法不会等待handle方法执行结束,而是立即返回
     * @param count
     * @param c
     */
    public void request(final int count, final char c){
        System.out.println("    request)" +count + " ," +c +") begin");
        //匿名内部类,创建一个新的线程去处理,该线程直接返回。
        new Thread(){
            @Override
            public void run() {
                helper.handle(count,c);
            }
        }.start();

        System.out.println("    request)" +count + " ," +c +") end");
    }
}
public class Test {

    public static void main(String[] args) {
        System.out.println("------BEGIN-----");
        Host host = new Host();
        host.request(10,'a');
        host.request(20,'b');
        host.request(30,'c');
        System.out.println("------END-------");
    }
}

三,模式特点

1.提高响应性,缩短延迟时间
当handle方法操作非常耗时的时候可以使用该模式。如果handle方法执行时间比创建一个新线程的时间还短,那就没必要了
2.操作顺序没有要求
handle方法并不一定是按照request方法的调用顺序来执行的。
3.适用于不需要返回值
request方法不会等待handle方法的执行结束。所以request得不到handle执行的结果

四,使用Runnable接口来创建并启动线程

代码:

public class Host2 {

    private final Helper helper = new Helper();

    /**
     * requst方法不会等待handle方法执行结束,而是立即返回
     * @param count
     * @param c
     */
    public void request(final int count, final char c){
        System.out.println("    request)" +count + " ," +c +") begin");
        //匿名内部类,创建一个新的线程去处理,该线程直接返回。
        /*new Thread(
                new Runnable() {
                    @Override
                    public void run() {
                        helper.handle(count,c);
                    }
                }
        ).start();*/
        Runnable runnable =new Runnable() {
            @Override
            public void run() {
                helper.handle(count,c);
            }
        };
        new Thread(runnable).start();
        System.out.println("    request)" +count + " ," +c +") end");
    }
}

优点:

当使用了Runnable的时候,我们可以自己写一个类,实现runnable。这样可以实现创建线程和线程内执行内容的分离,进行解藕。

五,ThreadFactory接口

上面的代码中有一个问题,Host类需要依赖于Thread类。我们可以考虑将线程的创建分离出去

public class Helper {

    public void handle(int count, char c){
        System.out.println("     handle("+count+" , "+c+") begin");
        for (int i = 0; i < count; i++) {
            slowly();
            System.out.print(c);
        }
        System.out.println("");
        System.out.println("     handle("+count+" , "+c +") end");
    }

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

        }
    }
}
/**
 * 
 * ThreadFactory接口中的方法:
 *  Thread newThread(Runnable r);
 */
public class Host {

    private final Helper helper = new Helper();
    private final ThreadFactory threadFactory;

    public Host(ThreadFactory threadFactory){

        this.threadFactory  = threadFactory;
    }

    public void request(final int count, final char c){
        System.out.println("    request)" +count + " ," +c +") begin");
        threadFactory.newThread(
                new Runnable(){
                    @Override
                    public void run() {
                        helper.handle(count,c);

                    }
                }
        ).start();

        System.out.println("    request)" +count + " ," +c +") end");
    }
}
public class Test {
    public static void main(String[] args) {
        System.out.println("------BEGIN-----");
        Host host = new Host(
                new ThreadFactory() {
                    @Override
                    public Thread newThread(Runnable r) {
                        return new Thread(r);
                    }
                }
        );
        host.request(10,'a');
        host.request(20,'b');
        host.request(30,'c');
        System.out.println("------END-------");
    }
}

通过java.util.concurrent.Executors类获取的ThreadFactory

public class Test2 {
    public static void main(String[] args) {
        System.out.println("------BEGIN-----");
        Host host = new Host(Executors.defaultThreadFactory());
        host.request(10,'a');
        host.request(20,'b');
        host.request(30,'c');
        System.out.println("------END-------");
    }

}

六,java.util.concurrent.Executor接口

public class Helper {

    public void handle(int count, char c){
        System.out.println("     handle("+count+" , "+c+") begin");
        for (int i = 0; i < count; i++) {
            slowly();
            System.out.print(c);
        }
        System.out.println("");
        System.out.println("     handle("+count+" , "+c +") end");
    }

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

        }
    }
}
/**
 * 
 * Executor接口中声明了execute方法: void execute(Runnable r);
 * Executor接口将 “处理的执行” 抽象化了,参数传入的Runnable对象表示 “执行的处理” 的内容
 * 隐藏了线程创建的的操作, 可以看到Host类中没有使用Thread,也没有使用ThreadFactory
 * 利用Host的其他类可以控制处理的执行
 */
public class Host {

    private final Helper helper = new Helper();
    private final Executor executor;

    public Host(Executor executor){

        this.executor= executor;
    }

    public void request(final int count, final char c){
        System.out.println("    request)" +count + " ," +c +") begin");
        executor.execute(
                new Runnable() {
                    @Override
                    public void run() {
                        helper.handle(count,c);
                    }
                }
        );

        System.out.println("    request)" +count + " ," +c +") end");
    }
}
public class Test {
    public static void main(String[] args) {
        System.out.println("------BEGIN-----");
        Host host = new Host(
                new Executor() {
                    @Override
                    public void execute(Runnable command) {
                        new Thread(command).start();
                    }
                }
        );
        host.request(10,'a');
        host.request(20,'b');
        host.request(30,'c');
        System.out.println("------END-------");
    }
}

七,ExecutorService接口

public class Helper {

    public void handle(int count, char c){
        System.out.println("     handle("+count+" , "+c+") begin");
        for (int i = 0; i < count; i++) {
            slowly();
            System.out.print(c);
        }
        System.out.println("");
        System.out.println("     handle("+count+" , "+c +") end");
    }

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

        }
    }
}
public class Host {

    private final Helper helper = new Helper();
    private final Executor executor;

    public Host(Executor executor){

        this.executor= executor;
    }

    public void request(final int count, final char c){
        System.out.println("    request)" +count + " ," +c +") begin");
        executor.execute(
                new Runnable() {
                    @Override
                    public void run() {
                        helper.handle(count,c);
                    }
                }
        );

        System.out.println("    request)" +count + " ," +c +") end");
    }
}
/**
 * 
 * ExecutorService接口 对可以反复execute的服务进行了抽象化,
 * 在ExecutorService接口后面,线程是一直运行着,每当调用execute方法时,线程就会执行Runnable对象
 * 可以复用那些执行结束后空闲下来的线程
 *
 */
public class Test {

    public static void main(String[] args) {
        System.out.println("------BEGIN-----");
        ExecutorService executorService = Executors.newCachedThreadPool();
        Host host = new Host(
                executorService
        );
        try {
            host.request(10,'a');
            host.request(20,'b');
            host.request(30,'c');
        }finally {
            executorService.shutdownNow();
        }

        System.out.println("------END-------");
    }
}
public class Helper {

public void handle(int count, char c){
System.out.println(" handle("+count+" , "+c+") begin");
for (int i = 0; i < count; i++) {
slowly();
System.out.print(c);
}
System.out.println("");
System.out.println(" handle("+count+" , "+c +") end");
}

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

}
}
}
原文地址:https://www.cnblogs.com/inspred/p/9425294.html