多线程系列之八: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 模式核心思想 如下的请求 ...
随机推荐
- 一、Selenium 工作原理
1.Selenium介绍 Selenium是用于测试Web应用程序用户界面UI的常用框架.端对端的功能测试.并且在一个多个浏览器中操作. 目前Seienium 组件主要包括Selenium IDE ...
- Windows10家庭版连接远程桌面出现credssp加密oracle修正问题
我发现我的win10不能连接别人的远程桌面,问题如下: 1.windows10家庭版需要修改注册表,家庭版没有组织策略: 2.win+R打开快速启动命令行输入"regedit": ...
- Unity 琐碎5 : 利用反射设置编辑器参数
问题 最近处理unity资源打包问题时候经常遇到的一个问题就是平台切换和Bundle编译.一般情况下,平台转换我需要依赖Cache Serbver加快转换速度,但是在Build Bundle的时候我又 ...
- Numpy 模块的应用
数据分析三剑客: Numpy, Pandas, Matplotlib NumPy(Numerical Python) 是 Python 语言的一个扩展程序库,支持大量的维度数组与矩阵运算,此外也针对数 ...
- centos7下安装docker(15.8docker跨主机容器通信总结)
性能:underlay网络的性能优于overlay.Overlay网络利用隧道技术,将数据包封装到UDP中进行传输,由于涉及数据包的封装和解封,存在额外的CPU和网络的开销,虽然几乎所有overlay ...
- 游览器发送http请求经过的步骤
OSI参考模型(Open System Interconnection,开放系统互连),全称为开放系统互联参考模型 ,OSI将计算机网络体系结构划分为了七层 TCP/IP协议族(TCP/IP Prot ...
- Python 属性与方法 概念理解
属性与方法 attribute(属性)是class(类)中的成员变量,而method(方法)则是class(类)中的function(函数). 也可以理解,属性就类变量,方法就是类函数. 类中的变量就 ...
- 【angularjs】使用angular搭建项目,获取dom元素
方法一:需要引入jq,否则会报angularJS1 Error: [jqLite:nosel](不建议使用) <div id="testID" class="tes ...
- 006_ansible1.9.6版本的安装
一.Linux的安装 cd /usr/local/src && wget https://pypi.python.org/packages/source/a/ansible/ansib ...
- ④---在Eclipse中导入GIT项目
Eclipse中导入GIT项目 以下将为大家介绍如何在Eclipse中导入GIT项目. 一.在Eclipse中安装GIT 1首先打开Eclipse,然后点击Help>Install New So ...