利用线程池实现ServerSocket的多客户端连接



利用线程池实现ServerSocket的多客户端连接

**利用线程池实现ServerSocket的多客户端连接**——————————
实际应用中,对于Socket通信而言基本都是多个客户端连接服务器端,因此简单的ServerSocket/Socket组合就无法满足要求了,而老是新开线程的话又太浪费资源,这里就用到Java自带的线程池ThreadPoolExcutor技术来实现多客户端连接服务端**

ThreadPoolExcutor类**
对原理很感兴趣的朋友可以直接看JDK源码,如果跟我一样对于纯英文的JDK看着头疼也可以度娘关于ThreadPoolExcutor类的源码解释,缺点就是不排除翻译可能不准确,所以看中文翻译版解释时注意仅作为参考,以实践为准,这里贴出一个解释的比较好的博客:

> http://www.cnblogs.com/zhanjindong/p/java-concurrent-package-ThreadPoolExecutor.html

获取ThreadPoolExcutor类的实例:

ThreadPoolExecutor pool=new ThreadPoolExecutor(5,10,3,TimeUnit.SECONDS,new ArrayBlockingQueue(1000));

四个参数的含义:

第一个,核心池大小;

第二个:最大线程数量,当线程数已经达到了核心池数量时,新添加的任务就会额外的开启新线程去运行,但不能超过第二个参数值,

第三个参数就是空闲线程休眠时间最大值,其单位就是第四个参数,超过这个最大值的空闲线程会被关掉,但总数量不会小于核心池大小;

第五个就是组塞队列,想要了解的可以度娘。

关于Socket就不详细的讲了,只贴出应用:

以下代码想看成效的只需要复制粘贴修改包名即可用,先开启服务类,然后开启第二个类,由于客户端代码一致,因此可以再建一个类把ClientSocket的代码复制一遍,然后运行,这样就模拟了两个客户端跟服务端的同时通信

第一个类,ServSocket:

package Chapter9;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.Scanner;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

//双向聊天应该建立在同样的端口,且由服务器发起,如果要由客户端发起,可以另开端口,客户端做服务器
//由于没有制作swing界面,因此在此处不提供由服务器端同时向多个客户端进行聊天的代码,但也实现了单个客户端连接时的双向聊天
public class ServSocket {

public static void main(String[] args) {
ServerSocket serverSocket;
ThreadPoolExecutor pool=new ThreadPoolExecutor(5,10,3,TimeUnit.SECONDS,new ArrayBlockingQueue(1000));
try {
Socket socket=null;
serverSocket = new ServerSocket(12001);
for(int i=0;i<2;i++){
socket=serverSocket.accept();
System.out.println(“—”+(i+1)+”号客户端连接成功”);
if(i==1){
i=0;//这里的作用在于保证即使客户端主动断开了连接,服务器也可以一直处于等待状态(不跳出循环),否则出了循环socket就将关闭
}
pool.execute(new ReaderHandle(socket));
}

new Thread(new WriteHandle(socket)).start();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

}
}
class ReaderHandle implements Runnable{
public Socket socket;
public ReaderHandle(Socket socket) {
// TODO Auto-generated constructor stub
this.socket=socket;
}

@Override
public void run() {
// TODO Auto-generated method stub
try {

System.out.println(“等待用户接入:”);
InputStreamReader in=new InputStreamReader(socket.getInputStream());
BufferedReader buffer=new BufferedReader(in);
String read=”";
try{
while((read=buffer.readLine())!=”quit”){//如果用户没有输入quit或者强行中断控制台,那么就可以保持持续连接
System.out.println(Thread.currentThread().getName()+”处理”+read);
}
}catch (SocketException e) {
// TODO: handle exception
System.out.println(“客户端主动断开连接”);//当用户强行中断控制台时会抛出SokcetException
}
socket.close();
in.close();
buffer.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}


}

}
class WriteHandle implements Runnable{//这个类的作用是向Socket里面写入数据,想用的话只需要连接单个客户端即可
public Socket socket;
public WriteHandle(Socket socket) {
// TODO Auto-generated constructor stub
this.socket=socket;
}

@Override
public void run() {
// TODO Auto-generated method stub
try {

OutputStream out=socket.getOutputStream();
PrintWriter printWriter=new PrintWriter(out);
System.out.println(“正在与客户端聊天:”);
BufferedReader buffer=new BufferedReader(new InputStreamReader(System.in));
while(true){//保证服务端可以一直跟客户端聊天
String str=buffer.readLine();
System.out.println(” 你:”+str);
printWriter.println(“来自服务器的消息:”+str);
printWriter.flush();
}
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

}

}
第二个类:ClientSocket:

package Chapter9;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner;

public class ClientSocket {

public static void main(String[] args) {
try {
Socket socket=new Socket(“localhost”, 12001);
//new Thread(new ReadHandle(socket)).start();
new Thread(new WrteHandle(socket)).start();

} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

}

}
//这里我关闭了从服务器的管道里读取流的类,毕竟没有很好的实现多客户端条件下的服务-客户单对单的聊天
/*
class ReadHandle implements Runnable{
public Socket socket;
public ReadHandle(Socket socket) {
// TODO Auto-generated constructor stub
this.socket=socket;
}
@Override
public void run() {
// TODO Auto-generated method stub
try {

InputStreamReader in=new InputStreamReader(socket.getInputStream());
BufferedReader buffer=new BufferedReader(in);
String read=”";
while((read=buffer.readLine())!=”quit”){

System.out.println(read);
}
socket.close();
in.close();
buffer.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

}

}
*/
class WrteHandle implements Runnable{
public Socket socket;
public WrteHandle(Socket socket) {
// TODO Auto-generated constructor stub
this.socket=socket;
}

@Override
public void run() {
// TODO Auto-generated method stub
try {

OutputStream out=socket.getOutputStream();
PrintWriter write=new PrintWriter(out);
System.out.println(“你想说:”);
BufferedReader buffer=new BufferedReader(new InputStreamReader(System.in));
while(true){
String str=buffer.readLine();
System.out.println(” 你:”+str);
write.println(“来自客户端的消息:”+str);
write.flush();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

}

}
———————
作者:monkeydie
来源:CSDN
原文:https://blog.csdn.net/monkeydie/article/details/78255680
版权声明:本文为博主原创文章,转载请附上博文链接!