用Java实现多线程服务器程序_百度文库_第1页
用Java实现多线程服务器程序_百度文库_第2页
用Java实现多线程服务器程序_百度文库_第3页
用Java实现多线程服务器程序_百度文库_第4页
用Java实现多线程服务器程序_百度文库_第5页
已阅读5页,还剩3页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、用Java实现多线程服务器程序        Java是伴随Internet的大潮产生的,对网络及多线程具有内在的支持,具有网络时代编程语言的一切特点。从Java的当前应用看,Java主要用于在Internet或局域网上的网络编程,而且将Java作为主流的网络编程语言的趋势愈来愈明显。实际工作中,我们除了使用商品化的服务器软件外,时常需要按照实际环境编写自己的服务器软件,以完成特定任务或与特定客户端软件实现交互。在实现服务器程序时,为提高程序运行效率,降低用户等待时间,我们应用了在Java Applet中常见的多线程技术。

2、一、Java中的服务器程序与多线程在Java之前,没有一种主流编程语言能够提供对高级网络编程的固有支持。在其他语言环境中,实现网络程序往往需要深入依赖于操作平台的网络API的技术中去,而Java提供了对网络支持的无平台相关性的完整软件包,使程序员没有必要为系统网络支持的细节而烦恼。Java软件包内在支持的网络协议为TCP/IP,也是当今最流行的广域网/局域网协议。Java有关网络的类及接口定义在包中。客户端软件通常使用包中的核心类Socket与服务器的某个端口建立连接,而服务器程序不同于客户机,它需要初始化一个端口进行监听,遇到连接呼叫,才与相应的客户机建立连接。J包的ServerSocket

3、类包含了编写服务器系统所需的一切。下面给出ServerSocket类的部分定义。1 public class ServerSocket 2 3 public ServerSocket(int port 4 throws IOException ;5 public Socket accept( throws IOException ;6 public InetAddress getInetAddress( ;7 public int getLocalPort( ;8 public void close( throws IOException ;9 public synchronized void

4、 setSoTimeout (int timeout throws SocketException ;10 public synchronized int getSoTimeout( throws IOException ; 11 12ServerSocket构造器是服务器程序运行的基础,它将参数port指定的端口初始化作为该服务器的端口,监听客户机连接请求。Port的范围是0到65536,但0到1023是标准Internet协议保留端口,而且在Unix主机上,这些端口只有root用户可以使用。一般自定义的端口号在8000到16000之间。仅初始化了ServerSocket还是远远不够的,它没

5、有同客户机交互的套接字(Socket,因此需要调用该类的accept方法接受客户呼叫。Accept(方法直到有连接请求才返回通信套接字(Socket的实例。通过这个实例的输入、输出流,服务器可以接收用户指令,并将相应结果回应客户机。ServerSocket类的getInetAddress和getLocalPort方法可得到该服务器的IP地址和端口。setSoTimeout和getSoTimeout方法分别是设置和得到服务器超时设置,如果服务器在timout设定时间内还未得到accept方法返回的套接字实例,则抛出IOException的异常。Java的多线程可谓是Java编程的精华之一,运用得

6、当可以极大地改善程序的响应时间,提高程序的并行性。在服务器程序中,由于往往要接收不同客户机的同时请求或命令,因此可以对每个客户机的请求生成一个命令处理线程,同时对各用户的指令作出反应。在一些较复杂的系统中,我们还可以为每个数据库查询指令生成单独的线程,并行对数据库进行操作。实践证明,采用多线程设计可以很好的改善系统的响应,并保证用户指令执行的独立性。由于Java本身是"线程安全"的,因此有一条编程原则是能够独立在一个线程中完成的操作就应该开辟一个新的线程。Java中实现线程的方式有两种,一是生成Thread类的子类,并定义该子类自己的run方法,线程的操作在方法run中实现

7、。但我们定义的类一般是其他类的子类,而Java又不允许多重继承,因此第二种实现线程的方法是实现Runnable接口。通过覆盖Runnable接口中的run方法实现该线程的功能。本文例子采用第一种方法实现线程。二、多线程服务器程序举例以下是我们在项目中采用的多线程服务器程序的架构,可以在此基础上对命令进行扩充。本例未涉及数据库。如果在线程运行中需要根据用户指令对数据库进行更新操作,则应注意线程间的同步问题,使同一更新方法一次只能由一个线程调用。这里我们有两个类,receiveServer包含启动代码(main(,并初始化ServerSocket的实例,在accept方法返回用户请求后,将返回的套

8、接字(Socket交给生成的线程类serverThread的实例,直到该用户结束连接。  1 /类receiveServer  2 import java.io.*;  3 import java.util.*;  4 import .*;   5   6 public class receiveServer  7 final int RECEIVE_PORT=9090; /该服务器的端口号  8 /receiveServer的构造器p

9、ublic receiveServer( ServerSocket rServer=null;  9 /ServerSocket的实例10 Socket request=null;11 /用户请求的套接字Thread receiveThread=null; 12 try13 rServer=new ServerSocket(RECEIVE_PORT; 14 /初始化ServerSocket System.out.println("Welcome to the server!"15 System.out.println(new Date(;16 Syste

10、m.out.println("The server is ready!"17 System.out.println("Port: "+RECEIVE_PORT;18 while(true /等待用户请求 request=rServer.accept(; /接收客户机连接请求receiveThread=new serverThread(request;19 20 /生成serverThread的实例21 receiveThread.start(;22 23 /启动serverThread线程24 25 26 catch(IOException e27 Sy

11、stem.out.println(e.getMessage( ;28 29 public static void main(String args new receiveServer(; 30 31 /end of main /end of class/类serverThreadimport java.io.*; 32 33 import .*;34 class serverThread extends Thread Socket clientRequest;35 /用户连接的通信套接字BufferedReader input; 36 /输入流PrintWriter output;37 /输出

12、流 38 public serverThread(Socket s 39 /serverThread的构造器 this.clientRequest=s;40 /接收receiveServer传来的套接字 InputStreamReader reader;41 42 OutputStreamWriter writer;43 try 44 /初始化输入、输出流 45 reader=new InputStreamReader(clientRequest.getInputStream(;46 writer=new OutputStreamWriter(clientRequest.getOutputSt

13、ream(; 47 input=new BufferedReader(reader; 48 output=new PrintWriter(writer,true; 49 50 catch(IOException e System.out.println(e.getMessage(;51 output.println("Welcome to the server!"52 /客户机连接欢迎词 53 output.println("Now is: "+new java.util.Date(+" "+ "Port:"+cl

14、ientRequest.getLocalPort(;54 output.println("What can I do for you?"55 56 57 public void run( 58 /线程的执行方法 59 String command=null;60 /用户指令 String str=null;61 boolean done=false;62 while(!done63 try64 str=input.readLine(;65 /接收客户机指令 66 catch(IOException e 67 System.out.println(e.getMessage(;

15、68 69 command=str.trim(.toUpperCase(; 70 71 if(str=null | command.equals("QUIT" /命令quit结束本次连接 72 done=true; 73 else if(command.equals("HELP" 74 /命令help查询本服务器可接受的命令 75 output.println("query"76 output.println("quit" 77 output.println("help" 78 79 else

16、if(command.startsWith("QUERY" 80 /命令81 query output.println("OK to query something!" 82 /else if . /在此可加入服务器的其他指令83 else if(!command.startsWith("HELP" && !command.startsWith("QUIT" && !command.startsWith("QUERY"output.println("Co

17、mmand not Found! 84 Please refer to the HELP!" 85 86 87 /end of while88 89 try90 91 clientRequest.close(;92 /关闭套接字93 94 catch(IOException e95 System.out.println(e.getMessage(;96 97 command=null;98 99 100 /end of run启动该服务器程序后,可用telnet machine port命令连接,其中machine为本机名或地址,port为程序中指定的端口。也可以编写特定的客户机软件

18、通过TCP的Socket套接字建立连接。        对象池的构造和管理可以按照多种方式实现。最灵活的方式是将池化对象的Class类型在对象池之外指定,即在ObjectPoolFactory类创建对象池时,动态指定该对象池所池化对象的Class类型,其实现代码如下:1 . . .2 3 public ObjectPool createPool(ParameterObject paraObj,Class clsType 4 5 return new ObjectPool(paraObj, clsType;6 7 8 9 .

19、. .10 11其中,paraObj参数用于指定对象池的特征属性,clsType参数则指定了该对象池所存放对象的类型。对象池(ObjectPool创建以后,下面就是利用它来管理对象了,具体实现如下:1 public class ObjectPool 2 private ParameterObject paraObj;/该对象池的属性参数对象3 private Class clsType;/该对象池中所存放对象的类型4 private int currentNum = 0; /该对象池当前已创建的对象数目5 private Object currentObj;/该对象池当前可以借出的对象6 pr

20、ivate Vector pool;/用于存放对象的池7 public ObjectPool(ParameterObject paraObj, Class clsType 8 this.paraObj = paraObj;9 this.clsType = clsType;10 pool = new Vector(;11 12 public Object getObject( 13 if (pool.size( <= paraObj.getMinCount( 14 if (currentNum <= paraObj.getMaxCount( 15 /如果当前池中无对象可用,而且已创建

21、的对象数目小于所限制的最大值,就利用16 /PoolObjectFactory创建一个新的对象17 PoolableObjectFactory objFactory =PoolableObjectFactory.getInstance(;18 currentObj = objFactory.create Object (clsType;19 currentNum+;20 else 21 /如果当前池中无对象可用,而且所创建的对象数目已达到所限制的最大值,22 /就只能等待其它线程返回对象到池中23 synchronized (this 24 try 25 wait(;26 catch (Int

22、erruptedException e 27 System.out.println(e.getMessage(;28 e.printStackTrace(;29 30 currentObj = pool.firstElement(;31 32 33 else 34 /如果当前池中有可用的对象,就直接从池中取出对象35 currentObj = pool.firstElement(;36 37 return currentObj;38 39 public void returnObject(Object obj 40 / 确保对象具有正确的类型41 if (obj.isInstance(clsT

23、ype 42 pool.addElement(obj;43 synchronized (this 44 notifyAll(;45 46 else 47 throw new IllegalArgumentException("该对象池不能存放指定的对象类型"48 49 50 从上述代码可以看出,ObjectPool利用一个java.util.Vector作为可扩展的对象池,并通过它的构造函数来指定池化对象的Class类型及对象池的一些属性。在有对象返回到对象池时,它将检查对象的类型是否正确。当对象池里不再有可用对象时,它或者等待已被使用的池化对象返回池中,或者创建一个新的对

24、象实例。不过,新对象实例的创建并不在ObjectPool类中,而是由PoolableObjectFactory类的createObject方法来完成的,具体实现如下:1 . . .2 public Object createObject(Class clsType 3 Object obj = null;4 try 5 obj = clsType.newInstance(;6 catch (Exception e 7 e.printStackTrace(;8 9 return obj;10 11 . . .这样,通用对象池的实现就算完成了,下面再看看客户端(Client如何来使用它,假定池化对

25、象的Class类型为StringBuffer:1 . . .2 /创建对象池工厂3 ObjectPoolFactory poolFactory = ObjectPoolFactory. getInstance (;4 /定义所创建对象池的属性5 ParameterObject paraObj = new ParameterObject(2,1;6 /利用对象池工厂,创建一个存放StringBuffer类型对象的对象池7 ObjectPool pool = poolFactory.createPool(paraObj,String Buffer.class;8 /从池中取出一个StringBuf

26、fer对象9 StringBuffer buffer = (StringBufferpool.getObject(;10 /使用从池中取出的StringBuffer对象11 buffer.append("hello"12 System.out.println(buffer.toString(; 13 . . .可以看出,通用对象池使用起来还是很方便的,不仅可以方便地避免频繁创建对象的开销,而且通用程度高。但遗憾的是,由于需要使用大量的类型定型(cast操作,再加上一些对Vector类的同步操作,使得它在某些情况下对性能的改进非常有限,尤其对那些创建周期比较短的对象。        由于通用对象池的管理开销比较大,某种程度上抵消了重用对象所带来的大部分优势。为解决该问题,可以采用专用对象池的方法。即对象池所池化对象的Class类型不是动态指定的,而是预先就已指定。这样,它在实现上也会较通用对象池简单些,可以不要ObjectPoolFactory和PoolableObjectFactory类,而将它们的功能直接融合到ObjectPool类,具体如下(假定被池化对象的Class类型仍为StringBuffer,而用省略号表示的地方,表示代码同通用对象池的实现

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论