多线程系列之八: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 = ; 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模式的更多相关文章
- Android进阶——多线程系列之Thread、Runnable、Callable、Future、FutureTask
多线程一直是初学者最抵触的东西,如果你想进阶的话,那必须闯过这道难关,特别是多线程中Thread.Runnable.Callable.Future.FutureTask这几个类往往是初学者容易搞混的. ...
- java多线程系列15 设计模式 生产者 - 消费者模式
生产者-消费者 生产者消费者模式是一个非常经典的多线程模式,比如我们用到的Mq就是其中一种具体实现 在该模式中 通常会有2类线程,消费者线程和生产者线程 生产者提交用户请求 消费者负责处理生产者提交的 ...
- 多线程系列之十:Future模式
一,Future模式 假设有一个方法需要花费很长的时间才能获取运行结果.那么,与其一直等待结果,不如先拿一张 提货单.获取提货单并不耗费时间.这里提货单就称为Future角色获取Future角色的线程 ...
- 多线程系列之七:Read-Write Lock模式
一,Read-Write Lock模式 在Read-Write Lock模式中,读取操作和写入操作是分开考虑的.在执行读取操作之前,线程必须获取用于读取的锁.在执行写入操作之前,线程必须获取用于写入的 ...
- 多线程系列之四:Guarded Suspension 模式
一,什么是Guarded Suspension模式如果执行现在的处理会造成问题,就让执行处理的线程等待.这种模式通过让线程等待来保证实例的安全性 二,实现一个简单的线程间通信的例子 一个线程(Clie ...
- Java多线程系列二——Thread类的方法
Thread实现Runnable接口并实现了大量实用的方法 public static native void yield(); 此方法释放CPU,但并不释放已获得的锁,其它就绪的线程将可能得到执行机 ...
- java多线程系列 目录
Java多线程系列1 线程创建以及状态切换 Java多线程系列2 线程常见方法介绍 Java多线程系列3 synchronized 关键词 Java多线程系列4 线程交互(wait和 ...
- Java多线程系列--“基础篇”03之 Thread中start()和run()的区别
概要 Thread类包含start()和run()方法,它们的区别是什么?本章将对此作出解答.本章内容包括:start() 和 run()的区别说明start() 和 run()的区别示例start( ...
- Java Thread系列(十)Future 模式
Java Thread系列(十)Future 模式 Future 模式适合在处理很耗时的业务逻辑时进行使用,可以有效的减少系统的响应时间,提高系统的吞吐量. 一.Future 模式核心思想 如下的请求 ...
随机推荐
- Linux中FTP的一点理解
FTP(File Transfer Protocol)是一个非常古老并且应用十分广泛的文件传输协议,FTP协议是现今使用最为广泛的网络文件共享协议之一,我们现在也一直有在用着FTP协议来进行各种文件的 ...
- 两个Map的对比,三种方法,将对比结果写入文件。
三种方法的思维都是遍历一个map的Key,然后2个Map分别取这2个Key值所得到的Value. #第一种用entry private void compareMap(Map<String, S ...
- 2016某知名互联网公司PHP面试题及答案(续)
1 写出mysql中,插入数据,读出数据,更新数据的语句 INSERT INTO 表名 VALUES ("",""): SELECT * FROM 表名:. U ...
- Servlet工作原理解析(tomcat7、嵌入式服务器)
目录 Servlet 容器Tomcat Servlet 容器的启动过程 Web 应用的初始化工作 Servlet 体系结构 创建 Servlet 对象(如何被加载) 初始化 Servlet(如何被 ...
- 超简单的gif图制作工具
测试成功了: 软件灵者Gif录制1.0 使用方法注意: 扩展: 安卓端想要制作gif可参考此方法(还没测试):https://blog.csdn.net/u012604745/article/deta ...
- 远程连接排错-屌丝去洗浴中心之路(windows)
1.查看道路是否通畅 ip地址是什么:就是我们要找的服务器在哪里 公网IP地址:全世界的任何地方都能访问到 私网IP地址:也指内网,私有环境,只在当前环境中.比如:192.168.0.??? 或者 1 ...
- 正则表达式工具RegexBuddy
1 下载 RegexBuddy 并安装 安装后的界面如下: 2 切换布局 点击右上角的彩色格子图标,选择 Side by Side Layout: 这种布局的好处是,Create 面板 ...
- BZOJ2521:[SHOI2010]最小生成树(最小割)
Description Secsa最近对最小生成树问题特别感兴趣.他已经知道如果要去求出一个n个点.m条边的无向图的最小生成树有一个Krustal算法和另一个Prim的算法.另外,他还知道,某一个图可 ...
- 邮票面值设计 (动态规划+DFS)
题意:https://ac.nowcoder.com/acm/problem/16813 思路: 深度搜索:每一层枚举一个面值,然后通过dp进行检查,并通过已知面值得到最多n张得到的最大表示数. 其实 ...
- 【转】MFC内嵌cef3浏览器内核
一.cef3内核的下载 可以从http://opensource.spotify.com/cefbuilds/index.html下载,注意:很多版本编译都可以通过 但是运行的时候会崩溃,以cef_b ...