1、Java 多线程技术在网络通信系统中的应用Java 语言是由 SUN 公司开发的适合于分布式计算的新一代面向对象程序设计语言,它是一种新的概念。首先,作为一种程序设计语言,它简单,面向对象,不依赖于机器的结构,具有可移植性,健壮性,安全性,多线程并且提供了并发机制,具有很高的性能。其次,它提供了强大和独特的网络通用机制和能力,极大简化了网络通信程序的繁琐细节,可不受 CPU 和环境的限制,Java 已成为当今网络最好的开发语言。一、Java 多线程简介将多线程机制蕴含在语言中,是 Java 的一个重要特征。所谓线程,是指程序中的一个执行流。在一个进程中,可以有多个线程。这些线程在操作系统的调度
2、下并发执行,使得每个线程都好像在独占整个系统资源。而有了多线程这个特性,JAVA 可以支持多个程序并发执行。利用 Java 的多线程编程接口,开发人员可以方便地写出支持多线程的应用程序,有效地减少并发并行程序设计的困难,提供程序执行效率。1.线程的创建有两种方法可以创建线程。第一种方法是通过继承类 Thread来创建线程类。子类重载其 mn0 方法。实现方法如下:classThieadNameextendsThreadpublicvoidrun()/run 是整个线程类代码的入口/需要以线程方式运行的代码第二种方法是建立一个具有 Runnable 接口的类。由于 Java不支持多继承性,如果需
3、要类似线程方式运行且继承其他的类,就必须实现 Runnable 接口。Runnable 接口只有一个方法 run()。在类中实现此接口的方法如下:classThieadNameextendsAppletimplementsRunnablepublicvoidrun()/需要以线程方式运行的代码2.线程的调用如果采用第一种方法,创建的线程类的调用格式如下:ThreadNametest=newThreadName();/test 是线程类ThreadName 的一个实例 test.start();start()是线程类的成员函数,用于启动该线程,该线程将自动调用 run()方法。如果采用第二种方法
4、,创建的线程类的调用格式如下:ThreadNametest=newThreadName();Threadth=newThiead(test);/组过 Thread 创建个新的线程th.start()3.线程的同步及通信系统中存在多个线程时,就需要保证线程的同步及相互通信,以期协调工作,避免发生死锁。Java 提供了二个标准的 Object 类方法 wait(),notify()和 notifyAll(),以及二个 Thread 类方法sleep()suspend()和 resume(),用于中断或唤醒线程的执行。当线程调用 sleep(),wait()或 suspend()方法之后线程就会由可
5、运行状态进入阻塞状态(blocked),一旦线程睡眠时间到或者是其他线程调用了 notify()或 resume()方法后,此线程才会由阻塞状态进入可运行状态中,然而一个线程是否最终占有 CPU,取决于系统的调度策略。Java1.0 在 solaris 版本中实现的“绿色线程”的调用策略是让一个线程持续处于执行状态直到有一个更高优先级的线程将之打断,而 Windows95 和 WindowsNT 是给每一个处于可执行状态的线程分配一个时间片,当时间片用完时系统会调用另一个线程投入运行。二、网间网的 Socket 通讯机制TCP/IP 技术的核心部分是传输层(TCP 和 UDP 协议)、网络层(
6、P 协议)和物理层(面向各种物理硬件技术),能实现这三层协议的内核可称之为 tcp/ip 网络操作系统。tcp/ip 协议技术中的中下层协议向外提供的只是原始的编程界面,而不是直接的用户服务,用户服务要靠核外的应用程序实现。应用程序和 tcp/ip 核心协议关系如图 2 所示。即网间网应用程序能够直接操作的是 TCP/P 核心协议提供的编程界面。由于网络中资源、运算能力和信息的差异,同时又由于网间网通信完全是异步的,因此,在基于 TCP/P 协议的网间网中,最主要的进程间相互作用模型是客户/服务器(client/server)模型。客户和服务器分别是两个应用程序(进程),客户向服务器发出服务请
7、求,服务器作出响应。网间网进程通信的关键是要解决进程的标识和多传输协议的标识问题以及进程间相互作用的模式。在网间网中,全局惟一的标识一个进程需要一个三兀组表示,即用半相关(half-association)来描述一个 Socket:协议,本地地址,本地端口号而一个完整的网间网进程通信需要由两个进程组成(两个端进程),因此一个完整的网间网进程通信必须用一个五元组表示,即用相关(association)来描述一个完整的 Socket:协议,本地地址,本地端口号,远地地址,远地端口号其中,一个确定的网间网进程通信只能使用同一个内核的高层协议,不可能通信的一端用TCP 而另一端用 UDP 协议。故而,
8、两个协议相同的半相关才能组成一个合适的相关,两个三元组组合起来是一个五兀组而非六兀组。每一个 Socket 有一个本地惟一的 Socket 号,由操作系统分配。一个本地 Socket 号,完整地描述了本地进程以及与之通信的远地进程,因此 Socket 的语义具有网络一致性,准确地描述了网络进程。因此,Socket 的关键是建立客户和服务器之间的相关。Socket 编程界面最早由 4BSDUNIX 系统提出,其主要目的是解决网间网进程通信(IPC)问题。故而,Socket 系统调用与 UNIX的文件访问有许多类似之处,是对 UNIX 输入输出的扩充。Socket是面向客户/服务器模型设计的,针对
9、客户和服务器程序提供了不同的 Socket 系统调用。服务器拥有全局公认的半相关 Socket,这就保证了任何客户都可以在网络的任何地方随机向它发出联接请求和信息请求。Socket 的数据信息是原始字节流的形式,通信双方要在此基础上进行约定的数据格式化和解释等处理(即相同的协议),然后才能进行进一步的具体应用操作,这也是实现某种协议的过程。基于 Socket 的这种通信机制,在网关(gateway)的作用下可实现TCP/协议和其他低级协议,如现场总线协议CAN(ControllerAreaNetwork)协议的转换,进而扩展 Internet 应用领域,将实时控制功能带入网络。Socket 通
10、信机制提供了两种通讯方式:有联接和无联接方式,分别面向不同的应用需求。使用有联接方式时,通信链路提供了可靠的,全双工的字节流服务。在该方式下,通信双方必须创建一个联接过程并建立一条通讯链路,以后的网络通信操作完全在这一对进程之间进行,通信完毕关闭此联接过程。使用无联接方式时其系统开销比有联接方式小,但通信链路提供了不可靠的数据报服务,不能保证信源所传输的数据一定能够到达信宿。在该方式下,通信双方不必创建一个联接过程和建立一条通讯链路,网络通信操作在不同的主机和进程之间转发进行。面向客户/服务器方式的 Socket 通信机制模型如图 3 所示。三、Java 多线程在网络编程中的应用1.Socke
11、t 客户端程序设计我们通过一个简单的应用程序实例来说明其通信程序的工作过程和编程特点。?Ximportjava.io.;X.;publicclassJabberServerpublicstaticfinalintPORT=8080;publicstaticvoidmain(Stringargs)throwsIOExceptionServerSockets=newServerSocket(PORT)System.out.println(“Started:”s)trySocketsocket=s.accept();trySystem.out.println(“Connectionaccepted:
12、”+socket)DatalnputStreamsi=newDataInputStream(socket.getInputStream();PrintSteamso=newPrintStream(socket.getOutputStream();while(true)Stringstr=in.readLine();if(str.equal(“END”) )break;System.out.println(“Echoing:”+str);System.out.println(str);finallySystem.out.println(“closing”?” ) ;此应用程序的功能是从输入流中获
13、取从服务器方发来的数据,并显示在屏幕上。Socket 类是覆盖在一个与平台有关的实现之上的,只是它把具体的系统细节从 java 程序中屏蔽了。因而在程序开始部分引入了 包中的所有的 Socket 类。基于此,Java 程序即可实现与平台的无关性。网络通信的目的主要是对网络资源的访问和操作。在建立了新的 Socket 对象实体 s 后,利用 outputStream(),getTnputStream()方法建立输出、输入流。这样,访问的网络资源的过程就变成了处理流对象的过程,即以数据流中的方法读写应用程序端。数据流(Stream)可以理解成数据的通信途径,在建立好应用程序和资源方的通信通道后,
14、远方的数据就可以自动传输过来。在程序的结尾用 close()方法关闭输入、输出流和 Socket,这样将释放所占用的系统资源。Java 语言的 Socket 通信机制和 UNIX 系统的输入输出操作(open-read-write-close)相类似。其客户端基本操作程序的编写概括起来包括以下四步:打开 Socket,即创建一个 Socket 对象实体:创建与此 Socket 联接的输入输出流;根据服务器的协议向此 Socket 写数据或从 Socket 读数据:关闭输入、输出流和Socket。2.Socket 服务器端程序设计基于 Java 语言的 Socket 服务器端基本操作过程和客户端
15、过程相对应,其程序的编写也包括以下五步:打开 SeneSocket,即创建一个 ServerSocket 对象实体在指定端口为客户端请求的 Socket 服务;使用 ServerSocket 类的accept()方法接收来自客户端的联接请求;使用新建的 Socket 对象创建输入、输出流对象;通过对流对象的操作完成客户端的处理请求,并将结果返回给客户端;当客户端和服务器工作结束时,关闭输入、输出流,用 ServerSocket 类的 close()方法关闭Sacket。服务器通常分为并发服务器和重复服务器,并发服务器只接收客户请求,不处理请求,客户请求由它的 fork 之进程处理和响应;而重复
16、服务器接收、处理.;publicclassMultiJabberServerpublicstaticfinalintPORT=8080;publicstaticvoidmain(Stringargs)throwsIOExceptionServeiSockets=newServerSocket(PORT);System.out.println(“ServerStarted”)trywhile(true)Socketsocket=s.accept()bynewMyserverHandler(socket)catch(IOExceptione)socket.close()finallysi.clos
17、e()so.close();s.close();(2)服务器端子线程程序的实现publicclassMyserverHandlerextendsThreadprivateSocketsocket;privateBufferReaderin;privatePrintWriterout;publicMyserverHandler(Sockets)throwsIOExceptionsocket=s;in=newBufferReader(newInputStreamReader(socket.getlnputStream();out=newPrintWriter(newBufferedWriter(n
18、ewOutStreamWriter(socket.getOutputStream()true);start();publicvoidiun()bywhile(true)Stringstc=in.readLine()if(str.equals(“END”)break;System.out.println(“Echoing:+str);out.pnintln(str)System.out.Println(“closing”?, , ) ;finallytrysocket.close();catch(IOException。 )1四、结语线程是系统调度和运行的最小单位,采用多线程能够开发出具有并行性和高可靠性的通信程序,并且可以节省系统资源。文中从原理和应用角度探讨了 Java多线程机制的实现技术结合一个具体的多用户并发服务器网络通信程序,说明开发网络通信程序的一般方法,所举实例对于实际网络通信程序的开发有一定的实用价值。