Thread-Per-Message模式是指每个message一个线程,message可以理解成“消息”、“命令”或者“请求”。每一个message都会分配一个线程,由这个线程执行工作,使用Thread-Per-Message Pattern时,“委托消息的一端”与“执行消息的一端”回会是不同的线程。
实例一:每一个任务一个线程
package com.zl.step24;
import java.util.concurrent.TimeUnit;
import static java.util.concurrent.ThreadLocalRandom.current;
public class TaskHandler implements Runnable {
private final Request request ;
public TaskHandler(Request request){
this.request = request ;
}
@Override
public void run() {
System.out.println("Begin handle : "+ request);
slowly();
System.out.println("End handle : "+ request);
}
private void slowly() {
try {
TimeUnit.SECONDS.sleep(current().nextInt(10));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
package com.zl.step24;
public class Request {
private final String business ;
public Request(String business){
this.business = business ;
}
@Override
public String toString(){
return business ;
}
}
package com.zl.step24;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Operator {
ExecutorService executorService = Executors.newFixedThreadPool(10);
public void call(String business){
TaskHandler taskHandler = new TaskHandler(new Request(business)) ;
executorService.execute(taskHandler);
executorService.shutdown();
}
}
package com.zl.step24;
import jdk.nashorn.internal.runtime.regexp.joni.constants.OPCode;
public class TPMTest {
public static void main(String[] args) {
Operator operator = new Operator();
operator.call("1");
operator.call("2");
operator.call("3");
operator.call("4");
operator.call("5");
}
}
实例二:多用户的网络聊天
package com.zl.step24;
import com.zl.step8.BasicThreadPool;
import com.zl.step8.ThreadPool;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
public class ChatServer {
private final int port ;
private ThreadPool threadPool ;
private ServerSocket serverSocket ;
public ChatServer(int port){
this.port = port ;
}
public ChatServer(){
this.port = 8888 ;
}
public void startServer() throws IOException{
this.threadPool = new BasicThreadPool(1,4,2,1000) ;
this.serverSocket = new ServerSocket(port) ;
this.serverSocket.setReuseAddress(true);
System.out.println("Chat server is start and listen at port : "+port);
this.listen();
}
private void listen() throws IOException {
for (;;){
Socket client = serverSocket.accept() ;
this.threadPool.execute(new ClientHandler(client));
}
}
}
package com.zl.step24;
import java.io.*;
import java.net.Socket;
public class ClientHandler implements Runnable {
private final Socket socket ;
private final String clientIdentify ;
public ClientHandler(final Socket socket){
this.socket = socket ;
this.clientIdentify = socket.getInetAddress().getHostAddress() + ":" + socket.getPort();
}
@Override
public void run() {
try {
this.chat();
} catch (IOException e) {
e.printStackTrace();
}
}
private void chat() throws IOException {
BufferedReader bufferedReader = wrap2Reader(this.socket.getInputStream());
PrintStream printStream = wrap2Print(this.socket.getOutputStream());
String received ;
while((received = bufferedReader.readLine() )!= null){
System.out.printf("client: %s-message:%s\n", clientIdentify , received );
if("quit".equals(received)){
write2Client(printStream,"client will close ....");
socket.close();
break;
}
write2Client(printStream,"Server: "+ received);
}
}
private void write2Client(PrintStream printStream, String message) {
printStream.println(message);
printStream.flush();
}
private PrintStream wrap2Print(OutputStream outputStream) {
return new PrintStream(outputStream) ;
}
private BufferedReader wrap2Reader(InputStream inputStream) {
return new BufferedReader(new InputStreamReader(inputStream));
}
}
package com.zl.step24;
import java.io.IOException;
public class ChatTest {
public static void main(String[] args) throws IOException {
new ChatServer().startServer();
}
}