我需要做的是编写一个服务器,接受多个客户端的请求并根据需要返回数据。.net的socket是这样来做的:首先,起一个线程listener等在那监 听端口,一旦有一个客户端连接,则监听端口线程新建一个accepter线程去处理建立连接的过程,与传统不一样的地方是新建完这个线程后这个 listener返回来继续监听,而不是一直做完所有的事情,同样的accepter线程再建立一个新的线程receiver去接收数据,而接收数据的线 程则根据收到的数据内容判断是否给与回复,如果需要回复,则同样新建一个线程sender,让这个send去写入数据。可以看出,整个组织形式的特点就是 将要做的事情交给别人去做,自己则回来继续做自己的事。 比如这里的几个角色listener,accepter,receiver,sender好比四个人,listener收到连接请求后告诉 accepter,这个地址来了请求,接下来交给你了,我继续回去监听;同样,accepter将接收数据交给receiver去做,而receiver 交给sender去做。通过这样明确的划分,不同的线程有了不同的权责,并且每个线程都可以focus自己的工作而不是一个人挑所有的重担。这样的组织就 是异步线程。
下面来看一个简单的例子,每次我们输入一行消息,就会新建一个线程将回显的任务交给它。
/**
* 2007-6-19
* Input.java
* package AsynchronizedThread
* TODO As a class which used to do input processing
* levi
*/package AsynchronizedThread;
import java.io.*;
public class Input {
public void listen() throws Exception{
String ch;
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
while(!(ch = in.readLine()).equals("EOF")){
new Output(ch).start();
}
}
}
/**
* 2007-6-19
* Output.java
* package AsynchronizedThread
* TODO As a asynchronized thread
* levi
*/
package AsynchronizedThread;public class Output extends Thread{
String msg;
public Output(String ch){
msg = ch;
}
public void run(){
System.out.println(msg);
}
}
/**
* 2007-6-19
* Test.java
* package AsynchronizedThread
* TODO As main test thread
* levi
*/package AsynchronizedThread;
import java.io.*;
public class Test {
public static void main(String [] args){
Input i = new Input();
try{
i.listen();
}
catch(Exception ioe){
}
}
}
而异步线程有一种变形,这里稍微提一下。在Doug lee的《concurrent programming in java design principles and patterns》 中曾提到并将其称为future pattern。这个变形跟异步线程不同的一点就是未来模式有返回值而异步线程没有。可能会很奇怪,既然有返回值,就意味着主线程要等待从线程返回值,这 样就变成了异步而不是同步。这正式未来模式精妙的地方,它先从从线程返回一个值,这个值不能立即使用,因为从线程并没有做完,但是一旦从线程完成了,主线 程就能得到这个值,就像现实中你用钱先去买到一张饭票,你却不能吃这张票,等到厨师做好了饭你才能拿着票去买饭。
乍看之下觉得跟异步线程并没有区别,其实异步线程是不能有返回值的,在需要有返回值的场合可 能就只会考虑到同步线程了,这样在吞吐量方面就不如未来模式,因为同步时主线程在等待,而异步时主线程却可以做自己的事情,做了一段时间再来拿那个被从线 程算出来的“值”,从而提高了吞吐。下图是未来模式的类图