一,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 = 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){
}
}
}