一,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. Ubuntu下vim打开文件时,提示请按ENTER或其它命令继续

    最近配置了一下vim,重启后,配置生效.但在用vim打开文件的时候,出现了一个问题:每次用vim打开文件的时候,都会提示请按ENTER或其它命令继续.这个真的很烦人.那么怎么把它消除掉呢? 首先要搞清 ...

  2. LeetCode算法题-Path Sum III(Java实现)

    这是悦乐书的第227次更新 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第94题(顺位题号是437).您将获得一个二叉树,其中每个节点都包含一个整数值.找到与给定值相加的路径数 ...

  3. python3编写网络爬虫23-分布式爬虫

    一.分布式爬虫 前面我们了解Scrapy爬虫框架的基本用法 这些框架都是在同一台主机运行的 爬取效率有限 如果多台主机协同爬取 爬取效率必然成倍增长这就是分布式爬虫的优势 1. 分布式爬虫基本原理 1 ...

  4. UVA1613-K-Graph Oddity(贪心)

    Problem UVA1613-K-Graph Oddity Accept: 108  Submit: 884Time Limit: 3000 mSec Problem Description Inp ...

  5. Python:Day17 生成器、time和random模块

    列表生成式: a = [x*2 for x in range(10)] #这是最简单的列表生成式,range换成其它的序列也OK a = [f(x) for x in range(10)] #将里将前 ...

  6. 网站建设部署与发布--笔记2-部署Apache

    网站部署(Linux) 部署Apache 操作系统:CentOS 7.2 1.首先连接云服务器,清楚系统垃圾. $ yum clean all Loaded plugins: fastestmirro ...

  7. Vim 去除因为 Unix 和 Windows 换行符不同带来的 ^M 问题

    由于各操作系统对换行符的处理不同, Unix: \n Windows : \r\n Mac : \r 所以有时 Vim 打开的文件会有如下情况: 解决方法为:在 Vim 中执行命令 :%s/\r//g ...

  8. Ubuntu 14.04 安装 CUDA 问题及解决

    本文安装环境: - 双显卡: intel 集显 + nvidia 独显 - Ubuntu 14.04.4 - CUDA 8.0.44 1. Deb 安装包是个坑 (不要用这种方法!) 使用 Deb 安 ...

  9. face recognition[MobiFace]

    本文来自<MobiFace: A Lightweight Deep Learning Face Recognition on Mobile Devices>,时间线为2018年11月.是作 ...

  10. Scala--模式匹配和样例类

    模式匹配应用场景:switch语句,类型查询,析构,样例类 一.更好的switch val ch :Char = '+' val sign = ch match{ case '+' => 1 c ...