菜鸟初学java的备忘录(九)
我突然发现了利用接口实现多线程和利用类构造线程体的不同了,以前我好像并没有太多的注意.利用类构造线程体的时候,需要使用这个类来定义线程对象,比如mythread thread1=new mythread(),而使用接口创建线程体的时候,只需要用到thread类就可以了,比如thread thread1=new thread(mythread).这在几天前所讲的多线程的socket中均有体现.
前面不懈的努力使我现在可以继续原先未完成的工作,正式向连接池版本的socket进发了.
回顾一下我们是如何创建多线程的服务器multithreadremotefileserver的,这得看看前几天的内容了.概括起来,就是为每个等待连接的客户new一个线程使用,来一个分配一个.每当有客户机申请一个连接时都在一个新 thread 中创建一个新 connectionhandler(注:使用接口构造的线程体).这意味着可能有一打 thread在整个系统中运行着.显然,系统的开销会因为连接客户的数目的增长而不断增加.我们不能够不考虑到开销增加到一定程度的时候系统会承受不住的可能.因此,得想个办法限制连接客户的数量,提高服务器的效率.
那么解决的方案是:在服务器端,我们在服务器启动时创建一定数量的pooledconnectionhandler,我们把进入的连接放入一个连接池中并让pooledconnectionhandler 打理剩下的事情.客户端的程序完全不用修改,这样设计的优点如下:
1.限定了允许同时连接的数目。
2.只需要启动pooledconnectionhandler线程有限次
这两句话的涵义将在其后的程序中得到体现,下面是 pooledremotefileserver 类的结构:
import java.io.*;可以看出,这个类与多线程socket那一天的connectionhandler非常相似,但不同的是,它带有处理连接池的手段.
import java.net.*;
import java.util.*;
public class pooledremotefileserver {
protected int maxconnections;//定义能同时处理的客户机连接的最大数目 protected int listenport;//定义要监听的端口号
protected serversocket serversocket;
public pooledremotefileserver(int alistenport, int maxconnections) {
listenport = alistenport;
this.maxconnections = maxconnections;
}
public static void main(string[] args) {
}
public void setuphandlers(){//创建数目为maxconnections的 pooledconnectionhandler
}
public void acceptconnections(){//在 serversocket 上监听传入的客户机连接,和前面的remotefileserver,multithreadremotefileserver中的监听程序完全一样
}
protected void handleconnection(socket incomingconnection) {
}//连接处理程序
}
同样,首先来看main函数
public static void main(string[] args) {
pooledremotefileserver server = new pooledremotefileserver(3000, 3);
server.setuphandlers();//同前面所有服务器的main函数不同,我们先要创建一个连接池,这个池里面有三个可用的connectionhandler
server.acceptconnections();//一旦就绪,就开始监听
下面我们就来看创建三个connectionhandler的程序如何实现:
public void setuphandlers(){
for (int i = 0; i < maxconnections; i++) {
pooledconnectionhandler currenthandler = new pooledconnectionhandler();
new thread(currenthandler, "handler " + i).start();
}
}
setuphandlers() 方法创建maxconnections个pooledconnectionhandler并在新 thread 中激活它们. pooledconnectionhandler在这里是一个用接口(runnable)实现的线程体.用实现了runnable的对象来创建thread使我们可以在 thread 调用 start() 并且可以期望在runnable上调用了 run()。也就是说,我们的 pooledconnectionhandler 将等着处理进入的连接,每个都在它自己的thread中进行。我们在示例中只创建三个thread,而且一旦服务器运行,这就不能被改变。
acceptconnections()方法这里就略去不写了,看看连接处理程序handleconnection(socket incomingconnection)
protected void handleconnection(socket connectiontohandle) {
pooledconnectionhandler.processrequest(connectiontohandle);
}
这里连接处理程序直接调用了pooledconnectionhandler线程类的类方法processrequest对监听到的连接进行处理,显然这个processrequest是一个静态方法.
pooledremotefileserver类中的方法均涉及到一个重要的线程类,pooledconnectionhandler.下面就看看这样一个用接口实现的类长什么样:
public class pooledconnectionhandler implements runnable {
protected socket connection;//代表当前正在处理的socket
protected static list pool = new linkedlist();//名为 pool 的静态 linkedlist 保存需被处理的连接,也就是用linkedlist来模拟一个连接池
public pooledconnectionhandler() {//构造函数
}
public void handleconnection() {//对连接的i/o操作在这里了
}
public static void processrequest(socket requesttohandle) {//处理客户连接,将他们加入连接池
}
public void run() {//等待有连接来,来了,就调handleconnection()处理
}
}
public static void processrequest(socket requesttohandle) {
synchronized (pool) {
pool.add(pool.size(), requesttohandle);
pool.notifyall();
}
}
public void run() {
while (true) {
synchronized (pool) {
while (pool.isempty()) {
try {
pool.wait();
} catch (interruptedexception e) {return;}
}
connection = (socket) pool.remove(0);//攫取池中的第一个连接,使之成为马上就要处理的connection
}
handleconnection();//然后交给handleconnection处理
}
}这个函数告诉了我们每个pooledconnectionhandler线程主要都在run些什么.显然,它是要不停的去看连接池中有没有接入的连接,如果有,马上处理,因此它在等待"连接池有连接了"这样一个条件.那么谁来告诉它这个条件满足了呢,显然是刚才的processrequest.当processrequest发出通知(pool.notify())的时候,这个条件就满足了,这时run()中的处理程序就不用再继续等待了,就可以马上去出一个连接进行处理.反过来说,在这个条件没有满足之前,wait()所在的线程还是要处于阻塞状态,或者是说停滞状态.由于同样要对pool进行操作,所以这里也需要使用到同步块.import java.io.*;
import java.net.*;
import java.util.*;
public class pooledremotefileserver {
protected int maxconnections;
protected int listenport;
protected serversocket serversocket;
public pooledremotefileserver(int alistenport, int maxconnections) {
listenport = alistenport;
this.maxconnections = maxconnections;
}
public void acceptconnections() {
try {
serversocket server = new serversocket(listenport, 5);
socket incomingconnection = null;
while (true) {
incomingconnection = server.accept();
handleconnection(incomingconnection);
}
} catch (bindexception e) {
system.out.println("unable to bind to port " + listenport);
} catch (ioexception e) {
system.out.println("unable to instantiate a serversocket on port: " + listenport);
}
}
protected void handleconnection(socket connectiontohandle) {
pooledconnectionhandler.processrequest(connectiontohandle);
}
public static void main(string[] args) {
pooledremotefileserver server = new pooledremotefileserver(3000, 3);
server.setuphandlers();
server.acceptconnections();
}
public void setuphandlers() {
for (int i = 0; i < maxconnections; i++) {
pooledconnectionhandler currenthandler = new pooledconnectionhandler();
new thread(currenthandler, "handler " + i).start();
}
}
}
class pooledconnectionhandler implements runnable {
protected socket connection;
protected static list pool = new linkedlist();
public pooledconnectionhandler() {
}
public void handleconnection() {
try {
printwriter streamwriter = new printwriter(connection.getoutputstream());
bufferedreader streamreader = new bufferedreader(new inputstreamreader(connection.getinputstream()));
string filetoread = streamreader.readline();
bufferedreader filereader = new bufferedreader(new filereader(filetoread));
string line = null;
while ((line = filereader.readline()) != null)
streamwriter.println(line);
filereader.close();
streamwriter.close();
streamreader.close();
} catch (filenotfoundexception e) {
system.out.println("could not find requested file on the server.");
} catch (ioexception e) {
system.out.println("error handling a client: " + e);
}
}
public static void processrequest(socket requesttohandle) {
synchronized (pool) {
pool.add(pool.size(), requesttohandle);
pool.notifyall();
}
}
public void run() {
while (true) {
synchronized (pool) {
while (pool.isempty()) {
try {
pool.wait();
} catch (interruptedexception e) {
return;
}
}
connection = (socket) pool.remove(0);
}
handleconnection();
}
}
}
Java Asp PHP .Net XML C/C++ CGI VB Jsp J2ee J2se J2me EJB Servlet Tomcat Resin Struts Weblogic Eclipse ANT GUI JMS Web servise IDEA Webphere Hibernate Spring Jboss Applet Swing Socket Javamail Perl Ajax P2P 安全 模式 框架 测试 开源 游戏
Windows XP Windows 2000 Windows 2003 Windows Me Windows 9.x Linux UNIX 注册表 操作系统 服务器 应用服务器