jdk6.0从入门到精通-----chapter8并发多线程(1)(源码下载)
服务器端使用线程池,每监听到一个请求,取出一个线程。当客户端输入stop时,消除线程池。
本例的线程池严格说算是线程数组,因为它丧失了两个很重要的网络服务器的特征:
1,主线程负责监听,一旦接入请求,将其转给线程池中空闲的线程处理,而自身继续监听客户端的连接请求。而本例中,主线程接入请求后继续负责调度线程池中线程处理客户端请求,这就导致了server只能接受一个client
2,线程池中线程一直处于运行状态
客户端
package ThreadPool1;import java.io.*;import java.lang.*;import java.net.*;import java.text.*;class ThreadManager{ TheThread[] runner=null; int count; boolean busy; public static void main(String[] args) throws IOException { new ThreadManager(5).listen(); } public ThreadManager(int count) { this.count=count; } private void listen() throws IOException { //建立线程池,启动所有线程 runner=new TheThread[this.count]; for(int i=0;i<this.count;i++) { runner[i]=new TheThread(i); runner[i].start(); } //侦听1024端口 ServerSocket serverSocket = new ServerSocket(1024); Socket socket = serverSocket.accept(); while(true) { try { BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream())); String cmd=in.readLine(); if(cmd==null) break; if(cmd.startsWith("stop")) { for(int i=0;i<5;i++) { synchronized(runner[i]) { Thread.sleep(500); runner[i].interrupt(); } } System.out.println("线程池已被销毁,程序退出"); break; } else synchronized(this) { busy=true; for(int i=0;i<5;i++) if(runner[i].string==null) { runner[i].string=cmd; busy=false; break; } if(busy) System.out.println("服务器正忙,线程池中没有空闲线程处理指令:"+cmd); } } catch(Exception e) { e.printStackTrace(); } } } }class TheThread extends Thread{ int no; public String string=null; public TheThread(int i) { this.no=i; } public void run() { try { while(true) { Thread.sleep(1000); if(this.string!=null) synchronized(this) { System.out.println("第"+no+"个线程处理指令:"+this.string); this.string=null; } } } catch(InterruptedException ie) { System.out.println("["+new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new java.util.Date())+"] "+"线程"+this.no+"被中止..."); } } }