• 《图解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){

    }
    }
    }
  • 相关阅读:
    进程和程序的关系
    进程和线程区别和联系
    什么是进程,进程的特征
    23.each和map函数
    22.仿淘宝五角星评论(链式编程、隐式迭代)
    19.阻止事件冒泡e.stopPropagation();
    18.阻止默认操作e.preventDefault();防止冒泡事件:e.stopPropagation()
    15.仿腾讯固定导航栏
    14.仿京东右侧边导航栏
    算法学习:树上差分
  • 原文地址:https://www.cnblogs.com/inspred/p/9425294.html
Copyright © 2020-2023  润新知