class Scanner implements Runnable{
String host;
int port;
Scanner(String host, int port){
this.host = host;
this.port = port;
}
public void run(){
Socket s = null;
try{
s = new Socket(InetAddress.getByName(host),port);
System.out.println("The port of " + port + " is opened.");
}catch(IOException ex){
}finally{
try{
if(s != null) s.close();
}catch(IOException e){
}
}
}
}
---------------------------------------------------------------------------------------------------------------------
PortScannerByThreadPool是主程序类,处理输入的4个参数(和第3个程序是一样的):主机名、开始端口、结束端口和线程数。Scanner类定义了真正的”任务“。在PortScannerByThreadPool中通过new ThreadPool(nThreads)创建ThreadPool对象,然后在for循环中通过new Scanner(host,i)创建”任务“对象,再通过tp.execute(ps)把”任务“对象添加到”池“中。
读者可以编译运行第4个程序,得出的结果和前面的是一样的。但是第4和第3个程序之间最大的差别就是:第4个程序会一直运行下去,不会自动结束。在第3个程序中存在一个isFinished()方法,可以用来判断任务是否处理完毕,而第4个程序中没有这样做。请读者自己思考这个问题。
在第3和第4个程序中,我们可以概括出多线程的模型。第3个程序的线程”池“里装的要处理的对象,第4个程序的线程”池“里装的是”工人“,还需要通过定义”任务“并给把它”派工“给”工人“。我个人比较偏好后者的线程池模型,虽然类的个数多了几个,但逻辑很清晰。不管怎样,第3和第4个程序中关键的部分都大同小异,就是2个synchronized程序块中的内容,如下(第4个程序中的):
synchronized(queue) {
queue.addLast(r);
queue.notifyAll();
}
和
synchronized(queue) {
while (queue.isEmpty()) {
try{
queue.wait();
}catch (InterruptedException ignored){
}
}
r = (Runnable) queue.removeFirst();
}
一般拿synchronized用来定义方法或程序块,这样可以在多线程同时访问的情况下,保证在一个时刻只能有一个线程对这部分内容进行访问,避免了数据出错。在第3个程序中通过List entries = Collections.synchronizedList(new LinkedList())来定义”池“,在第4个程序中直接用LinkedList queue,都差不多,只是Collections.synchronizedList()可以保证”池“的同步,其实”池“里的内容访问都是在synchronized定义的程序块中,所以不用Collections.synchronizedList()也是可以的。
wait()和notifyAll()是很重要的,而且这2个方法是Object基类的方法,所以任何一个类都是可以使用的。这里说明一个可能产生混淆的问题:queue.wait()并不是说queue对象需要进行等待,而是说queue.wait()所在的线程需要进行等待,并且释放对queue的锁,把对queue的访问权交给别的线程。如果读者对这2个方法难以理解,建议参考JDK的文档说明。
好了,通过以上4个例子的理解,读者应该能对多线程的程序设计有了一定的理解。第3和第4个程序对应线程模型是非常重要的,可以说是多线程程序设计过程中不可或缺的内容。
如果读者对以上的内容有任何疑问,可以和我联系,qianh@cntmi.com 版权所有,严禁转载
参考资料:
1、《Java Networking Programming, 3rd》written by Elliotte Rusty Harold, Published by O'Reilly,2004
2、“Thread pools and work queues” written by Brian Goetz, Principal Consultant, Quiotix Corp.
查看本文来源