一,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 = ; i < count; i++) {
slowly();
System.out.print(c);
}
System.out.println("");
System.out.println(" handle("+count+" , "+c +") end");
} public void slowly(){
try {
Thread.sleep();
}catch (InterruptedException e){ }
}
}

多线程系列之八:Thread-Per-Message模式的更多相关文章

  1. Android进阶——多线程系列之Thread、Runnable、Callable、Future、FutureTask

    多线程一直是初学者最抵触的东西,如果你想进阶的话,那必须闯过这道难关,特别是多线程中Thread.Runnable.Callable.Future.FutureTask这几个类往往是初学者容易搞混的. ...

  2. java多线程系列15 设计模式 生产者 - 消费者模式

    生产者-消费者 生产者消费者模式是一个非常经典的多线程模式,比如我们用到的Mq就是其中一种具体实现 在该模式中 通常会有2类线程,消费者线程和生产者线程 生产者提交用户请求 消费者负责处理生产者提交的 ...

  3. 多线程系列之十:Future模式

    一,Future模式 假设有一个方法需要花费很长的时间才能获取运行结果.那么,与其一直等待结果,不如先拿一张 提货单.获取提货单并不耗费时间.这里提货单就称为Future角色获取Future角色的线程 ...

  4. 多线程系列之七:Read-Write Lock模式

    一,Read-Write Lock模式 在Read-Write Lock模式中,读取操作和写入操作是分开考虑的.在执行读取操作之前,线程必须获取用于读取的锁.在执行写入操作之前,线程必须获取用于写入的 ...

  5. 多线程系列之四:Guarded Suspension 模式

    一,什么是Guarded Suspension模式如果执行现在的处理会造成问题,就让执行处理的线程等待.这种模式通过让线程等待来保证实例的安全性 二,实现一个简单的线程间通信的例子 一个线程(Clie ...

  6. Java多线程系列二——Thread类的方法

    Thread实现Runnable接口并实现了大量实用的方法 public static native void yield(); 此方法释放CPU,但并不释放已获得的锁,其它就绪的线程将可能得到执行机 ...

  7. java多线程系列 目录

    Java多线程系列1 线程创建以及状态切换    Java多线程系列2 线程常见方法介绍    Java多线程系列3 synchronized 关键词    Java多线程系列4 线程交互(wait和 ...

  8. Java多线程系列--“基础篇”03之 Thread中start()和run()的区别

    概要 Thread类包含start()和run()方法,它们的区别是什么?本章将对此作出解答.本章内容包括:start() 和 run()的区别说明start() 和 run()的区别示例start( ...

  9. Java Thread系列(十)Future 模式

    Java Thread系列(十)Future 模式 Future 模式适合在处理很耗时的业务逻辑时进行使用,可以有效的减少系统的响应时间,提高系统的吞吐量. 一.Future 模式核心思想 如下的请求 ...

随机推荐

  1. Django中间件的使用

    Django中间件的使用 中间件(middleware) 中间件应用于request与服务端之间和服务端与response之间,客户端发起请求到服务端接收可以通过中间件,服务端返回响应与客户端接收响应 ...

  2. 第十四届智能车队员培训 I/O的使用 数据方向寄存器和数据寄存器的配置 MC9S12D64处理器

    I/O的使用 数据方向寄存器和数据寄存器的配置 I/O输入输出的使用: 数据方向寄存器与数据寄存器 寄存器的概念: 寄存器,是集成电路中非常重要的一种存储单元,通常由触发器组成.在集成电路设计中,寄存 ...

  3. 02.Python网络爬虫第二弹《http和https协议》

    一.HTTP协议 1.官方概念: HTTP协议是Hyper Text Transfer Protocol(超文本传输协议)的缩写,是用于从万维网(WWW:World Wide Web )服务器传输超文 ...

  4. 阿里云CentOS下nodejs安装

    1. 下载node包(包含npm) cd /usr/local/src/ wget https://nodejs.org/dist/v10.11.0/node-v10.11.0-linux-x64.t ...

  5. PostgreSQL条件表达式 case when then end

    例: SELECT CASE WHEN (store_size <= (100)::NUMERIC) THEN '小店'::TEXT WHEN (store_size >= (200):: ...

  6. 阿里云windows server 2012 TIME_WAIT CLOSE_WAIT

    新申请的阿里云windows server 2012 R2上部署安装了socket服务器,但客户端连接后老是断开(心跳包没有),服务假死(服务不断也走),客户端申请连接会也会死在cmd下输入指令 ne ...

  7. C#释放资源文件dll或exe

    将程序包含的资源文件释放到硬盘上 1.VS2017-新建  winform(窗体应用)命名为 loader 2.在解决方案管理器中,展开项目loader 在 properties 下面,找到[Reso ...

  8. 【js】横/纵向无缝滚动

    1.纵向无缝滚动(类似淘宝) ps:存在一个问题,当鼠标移入时,未关闭定时器 <!DOCTYPE html> <html> <head> <meta char ...

  9. 14 python初学(高阶函数 递归函数 内置函数)

    高阶函数:1.  函数名是一个变量,函数名可以进行赋值 2. 函数名可以作为函数参数,还可以作为函数返回值(函数名称作为函数返回值时返回的是:函数的地址:print 这个返回值的调用相当于执行这个函数 ...

  10. apache反向代理出现502调整

    1.问题描述:项目上线后,会在接口调用时客户端出现502异常,而服务端则对该此请求作出处理. 2.问题原因:经过排查后得知是由于请求并发量大,造成超过请求超时间,但是apache中队列已经加载到请求信 ...