多线程thread-per-message设计模式+异步消息

感谢看了这篇书 我才终于懂了异步消息的概念

异步

本节和下一节线程池进行异步 是 异步的两大主要形式

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  1. 现实场景:主任委托员工A去打印 委托员工B去买水 主任不关心他们返回的结果
    主任就接着做自己的事情了

  2. 该模式又成为多线程下的代理模式 多线程下的适配器模式

该模式需要以下几个角色:

  • 客户访问类
  • 代理类 Host 在客户端只创建一个host实例
  • 被代理类 Helper
class Client{
    public static void main(String[] args) {
        System.out.println(Thread.currentThread().getName()+"调用主线程");
        Host h=new Host();
        h.request("mysql");
        h.request("mq");
        System.out.println(Thread.currentThread().getName()+"调用主线程结束");
    }
}
public class Host {
    private final Helper helper=new Helper();

    public void request(String s){
        System.out.println(Thread.currentThread().getName()+"调用request");
        new Thread(new Runnable() {
            @Override
            public void run() {
                helper.handle(s);
            }
        }).start();
        System.out.println(Thread.currentThread().getName()+"调用request结束");
    }

}
public class Helper {

    public void handle(String s){
        try {
            System.out.println(Thread.currentThread().getName()+"调用handler处理"+s);
            Thread.sleep(1000);
            System.out.println(Thread.currentThread().getName()+"调用handler结束");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

在host类中 新启线程去调用helper中的handle
不论handle方法执行多久 客户端永远很快获得host方法Request响应

handle中的sleep时间加长 客户端需要等待更久的时间么?

主线程顺序调用客户端请求的request方法
request方法里让helper帮忙做这件事 帮忙做那件事 吩咐完这些命令 委托完这些功能 主线程就可以终止了

request方法里新启动的线程 消耗多久的时间都不会影响request的响应性 他不等待handler方法结束 而是立即结束并响应 之后那些helper会自行做工作
在这里插入图片描述

每次调用request都会创建一个helper新实例?

nope

现实场景1:服务器

面对众多的请求 只有一个服务器 Host
服务器为每一个请求都新建一个线程

  • 尤其现在的请求涉及大量的IO操作 输入输出 或者长时间的业务逻辑
    我们在服务器中正常响应客户端(比如说显示操作成功 )
    但是具体的业务给其他线程跑 保证了服务器的响应速度

下面是一个非常简单的demo

public class WebServer {
    private final MyService service = new MyService();
    private int port;

    public WebServer(int port) {
        this.port = port;
    }

    public void execute() throws IOException {
        ServerSocket serverSocke = new ServerSocket(port);
        try {
            while (true) {
                final Socket client = serverSocke.accept();
                service.service(client);
            }
        } finally {
            serverSocke.close();
        }

    }
}

class MyService {
    public void service(final Socket clientSocket) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    doService(clientSocket);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }

    public void doService(Socket clientSocket) throws InterruptedException {
      
    }
}
现实场景2:多次刷新请求 如何处理

上面的小demo 没有做service那边多线程的处理
如果频繁的刷新网页

  • 是否只让一个请求好使 就不用管之后刷新的请求了

模拟有一个按钮 我们点击一次就控制台打印 就模拟请求服务器一样
我们多次点击 模拟多次刷新看会出现什么问题

public class Button {
    final ButtonService service = new ButtonService();

    public void request() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    service.doService();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }).start();

    }

    public static void main(String[] args) {
        Button button = new Button();
        button.request();
        button.request();
    }
}

class ButtonService {
    public void doService() throws InterruptedException {
        System.out.print(Thread.currentThread().getName());
        for (int i = 0; i < 10; i++) {
            Thread.sleep(100);
            System.out.print(i);
        }
        System.out.println("done!");
    }
}

在这里插入图片描述
混合输出 交替打印
而且点击两次 其实不用请求两次 一次就可以
在这里插入图片描述
按序打印 但是还是请求了两次 没必要
在这里插入图片描述
在这里插入图片描述

class ButtonService {
     private  static  volatile   boolean  workAlready=false;
    public synchronized void  doService() throws InterruptedException {
        if(workAlready){
            System.out.println(Thread.currentThread().getName()+"被阻塞");
            return ;
        }
        System.out.print(Thread.currentThread().getName());
        for (int i = 0; i < 10; i++) {
            Thread.sleep(100);
            System.out.print(i);
        }
        System.out.println("done!");
        workAlready=true;

    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值