动态网站制作指南 [  QQ表情  ]
[ 投票调查 ]
[ 企业邮箱 ]
[ 网站空间 ]
网络编程 | 站长之家 | 网页制作 | 图形图象 | 操作系统 | 冲浪宝典 | 软件教学 | 网络办公 | 邮件系统 | 网络安全 | 认证考试 | 系统进程
ASP源码 | .Net源码 | PHP源码 | JSP源码 | JAVA源码 | CGI源码 | VB源码 | C++源码 | Delphi源码 | PB源码 | VF源码 | 汇编 | 服务器
Firefox | IE | Maxthon | 迅雷 | 电驴 | BitComet | FlashGet | QQ | QQ空间 | Vista | 输入法 | Ghost | Word | Excel | wps | Powerpoint
asp | .net | php | jsp | Sql | c# | Ajax | xml | Dreamweaver | FrontPages | Javascript | css | photoshop | fireworks | Flash | Cad | Discuz!
当前位置 > 网站建设学院 > 网络编程 > Java教程
Tag:注入,存储过程,分页,安全,优化,xmlhttp,fso,jmail,application,session,防盗链,stream,无组件,组件,md5,乱码,缓存,加密,验证码,算法,cookies,ubb,正则表达式,水印,索引,日志,压缩,base64,url重写,上传,控件,Web.config,JDBC,函数,内存,PDF,迁移,结构,破解,编译,配置,进程,分词,IIS,Apache,Tomcat,phpmyadmin,Gzip,触发器,socket
网络编程:ASP教程,ASP.NET教程,PHP教程,JSP教程,C#教程,数据库,XML教程,Ajax,Java,Perl,Shell,VB教程,Delphi,C/C++教程,软件工程,J2EE/J2ME,移动开发
文章搜索服务
邮件订阅
输入你的邮件地址,
你将不会错过任何关于:
[ Java教程 ]的信息

本月文章推荐
.一个软件测试工程师的加班经历.
.学习使用J2EE Web应用的事件功能.
.05年11月程序语言世界排行-Java居.
.编程应用实例:Java通过JNI与Del.
.WebLogic Server 9.0 应用配置管.
.我们组的Web应用开发方式.
.J2EE应用开发中与Oracle数据库的.
.java中的对象引用问题的再次理解.
.javamail 处理html信件的方法,包.
.如何在SPRING中实现事务暂停.
.Java做一个最简单的通话程序.
.开天劈地:开发 JAVA 程序的新武.
.java小程序中鼠标事件的响应处理.
.按需变化解释有状态还是无状态EJ.
.2005年Java十大热点问题揭晓.
.JBoss中EJB的开发.
.Struts 用户指南(一).
.用Struts开发基于MVC的Web应用.
.在开始时击败递归类强制转换概念.
.调整JavaTM 的I/O性能(一)(zt).

菜鸟初学Java的备忘录(九)

发表日期:2008-1-5 |



我忽然发现了利用接口实现多线程和利用类构造线程体的不同了,以前我似乎并没有太多的注重.利用类构造线程体的时候,需要使用这个类来定义线程对象,比如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.*;
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()处理
}
}

可以看出,这个类与多线程Socket那一天的ConnectionHandler非常相似,但不同的是,它带有处理连接池的手段.

首先看看要在监听程序中用到的processRequest()方法
public static void processRequest(Socket requestToHandle) {
synchronized (pool) {
pool.add(pool.size(), requestToHandle);
pool.notifyAll();
}
}

这里的requestToHandle就是要处理的客户连接socket.可以这样说,processRequest所做的工作就是把客户连接加入到连接池当中.但是要确保在对连接池(Pool)进行操作的时候没有其他的线程干扰,就需要获取连接池的对象锁,并使用同步块,前面所了解有关synchronized的概念在这里就可以派上用场了.

那么,既然已经保证了我们是唯一“涉水”的人,我们就可以把传入的 Socket 添加到 LinkedList 的尾端.一旦我们添加了新的连接,我们就可以使用pool.notifyall通知其它正在等待该池的 Thread,连接池的对象锁解除,现在可用了.从另外一个角度来说,也可以说是通知另外一个正在等待的线程,一些条件已经具备了.

那么这个在等待的线程是什么呢?

我们来实现PooledConnectionHandler上的run()方法,它将在连接池上等待,并且池中一有连接就处理它,所以是这个要处理连接的线程在等待着呢:

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进行操作,所以这里也需要使用到同步块.

让我们再次复习一下对象锁的概念.当 run() 拥有池的互斥锁时,processRequest() 如何能够把连接放到池中呢?答案是对池上的 wait() 的调用释放锁,而 wait() 接着就在自己返回之前再次攫取该锁。这就使得池对象的其它同步代码可以获取该锁。

最后,我们看看PooledConnectionHandler线程中的handleConnection()方法.跟在多线程服务器中不同,我们的PooledConnectionHandler有一个 handleConnection() 方法。这个方法的代码跟非池式的,也就是多线程服务器中的ConnectionHandler上的 run() 方法的代码完全一样。首先,我们把 OutputStream 和 InputStream 分别包装进(用 Socket 上的 getOutputStream() 和 getInputStream())BufferedReader 和 PrintWriter。然后我们逐行读目标文件,就象我们在多线程示例中做的那样。再一次,我们获取一些字节之后就把它们放到本地的 line 变量中,然后写出到客户机。完成读写操作之后,我们关闭 FileReader 和打开的流。

讲到这里,我们可以看到,程序中有两个类,PooledRemoteFileServer和PooledConnectionHandler.PooledRemoteFileServer并不直接处理连接请求,它只是负责监听这些连接,并把他们仍到连接池里面,至于处理的具体环节,都交给PooledConnectionHandler负责了。

我们的带有连接池的服务器研究完了。让我们回顾一下创建和使用“池版”服务器的步骤:

1.创建一个新种类的连接处理程序(我们称之为 PooledConnectionHandler)来处理池中的连接。
2.修改服务器以创建和使用一组 PooledConnectionHandler。

附:PooledRemoteFileServer.java的源码

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的备忘录(十) 人气:530
下一篇:菜鸟初学Java的备忘录(八) 人气:463
浏览全部Java的内容 Dreamweaver插件下载 常用网页广告代码全集
  最新网站源码 最新软件下载
2008-12-2 OpenPNE中文 v2.12.5 for win 中
2008-12-2 谷秋精品课程软件课程版 v2.3
2008-12-2 晴天电影系统(带一键迅雷/自定义
2008-12-2 QQip138闪字程序
2008-12-2 SmartWeb企业智能建站系统 v1.0.2
2008-12-2 梦想不死个人主页 v2009
2008-12-2 开良ASP小偷程序生成器 v1.1
2008-12-2 toolxp.cnalexa世界排名查询 php
2008-12-2 腾讯留言板 v1.3
2008-11-29 Tencent Traveler 4.4
2008-11-29 龙卷风网络收音机 v3.0.0.0
2008-11-29 Intel Chipset Software Install
2008-11-29 TweakVI 1.0 Build 1100
2008-11-29 Opera 9.62 Build 10469
2008-11-29 MPlayer WW编译版 SVN-r28044(20
2008-11-29 NetTools网络工具v1.0.0破解版
2008-11-29 3DGallery三维体验1.1破解版
2008-11-29 SecretBook保密本v1.0破解版
  发表评论
姓 名: 验证码:
内 容:
站长工具:网站收录查询 | Google PR查询 | ALEXA排名查询 | CSS在线编辑器 | OPEN参数生成器 | 弹出式窗口代码产生器 | 密码登录生成器 | 在线按钮生成器 | Meta标签生成器 | 多色彩特效字代码生成器 | 网页代码调试器 | 在线FTP登陆 | Flash取色器 | 配色代码对照表 | 配色辞典 | CSS生成器 | 广告代码 | 框架网页代码生成器 | js/vbs加密 | md5加密 | 进制转换 | UTF-8 转换工具 | 在线调色板 | Html转换js | Html转换asp | Html转换php | Html转换perl
实用工具:汉字翻译拼音 | 拼音字典 | 符号对照表 | 个税计算 | 实时汇率查询换算 | 经典小工具 | 汉字简繁转换 | 普通单位换算 | 公制单位换算 | 生辰老黄历 | 国内电话区号 | 国家代码与域名缩写 | 文字加密解密 | 元素周期表 | 健康查询 | 世界时间 | 万年历 | 二十四节气 | 汉字横竖排版 | 手机号码查询 | 计算器 | ip搜索
业务联系 | 广告刊登 | 频道合作 | 投稿荐稿 | 联系方式 | 加入收藏 | RSS订阅
Copyright © 2000-2009 www.knowsky.com All rights reserved | 沪ICP备05001343号
ホームページ制作 不動産検索システム 求人情報
防水工事·改修工事 フットサル大会 探偵
SEO対策 中国語教室 ホームページ作成