一,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. 创建属于其他Session的进程

    创建其他Session(User)的进程需要拿到对应Session的Token作为CreateProcessAsUser的参数来启动进程. 修改有System权限的Token的TokenId为其他Se ...

  2. 【转】10条你不可不知的css规则

    10条你不可不知的css规则 Posted on 2006-12-20 10:33 雨中太阳 阅读(343) 评论(1) 编辑 收藏 :[译]10条你不可不知的css规则正文: Published D ...

  3. SpringCloud之初识Hystrix熔断器 ----- 程序的保护机制

    在上一篇的-负载均衡Robbin中,我们简单讲解到负债均衡的算法和策略.负载均衡就是分发请求流量到不同的服务器,以减小服务器的压力和访问效率,但是当负载均衡的某个服务器或是服务挂掉之后,那么程序会出现 ...

  4. 我使用的Bem的习惯

    在基于BEM命名思想的基础上,我整理一些实用的点: BEM,B即block(块),E即element(元素),M即modifier(修饰符) 块:最顶层,可包含块和元素 元素:被块包含,通常为最终被包 ...

  5. rem实现自适应

    总结一下,rem实现自适应:用rem代替px,配合媒体查询设置font-size:n%. 首先,px是死的.若一律用px,那就会大的显得小,小的屏幕显得大.其次,rem是活的,通过设置字体大小可以引起 ...

  6. 为什么二流程序员都喜欢黑php?

    为什么二流程序员都喜欢黑php? 为什么程序员都喜欢黑php?这个嘛!你骂一句php是垃圾试试,保准php程序员不揍扁你!这就好像自己的母校,纵然有很多不好的地方,但是只允许自己调侃,不允许外人骂半句 ...

  7. 字符串相关的hash值(一)

  8. DVR登录绕过漏洞(CVE-2018-9995)

    ###漏洞描述 此漏洞允许攻击者通过修改“Cookie: uid=admin” 之后访问特定 DVR 的控制面板,返回此设备的明文管理员凭证. ###漏洞利用 1.利用代码 curl "ht ...

  9. 吴恩达课后作业学习2-week1-2正则化

    参考:https://blog.csdn.net/u013733326/article/details/79847918 希望大家直接到上面的网址去查看代码,下面是本人的笔记 4.正则化 1)加载数据 ...

  10. solidity learning (1)

    学习文档笔记:http://solidity-cn.readthedocs.io/zh/develop/layout-of-source-files.html 1.pragma solidity ^0 ...