【Socket】三、Socket使用线程池支持多个线程同时访问
一、使用循环不断接受客户端发送的消息
首先将第二节的TCPServer改造,使用while(true)让服务器能够一直接收客户端发送的信息。
同时使用try-finally语法块关闭连接。
public class TcpServer {
public static void main(String[] args) throws IOException {
System.out.println("socket服务器端启动....");
ServerSocket serverSocket = new ServerSocket(8088);
try {
while (true){
//获取客户端对象
Socket accept = serverSocket.accept();
InputStream inputStream = accept.getInputStream();
byte[] buf= new byte[1024];
int len=inputStream.read(buf);
String str =new String(buf,0,len);
System.out.println("str:" + str);
}
} finally {
serverSocket.close();
}
}
}
使用浏览器不断访问 http://127.0.0.1:8088/ 地址,控制台会一直打印访问信息。
缺点:只能支持一个客户端访问,无法支持多个同时访问。
二、使用线程池优化访问
注意这里为什么不使用多线程而是线程池。因为线程池可以放入缓存队列。线程池其实就是多线程,提前提供了线程放入线程池,调用时供调用方使用,会出个专题专门讲线程池,这里只说使用。
在之前代码基础上,添加了线程池,此时代码可供多个客户端同时访问,So easy!
public static void main(String[] args) throws IOException {
System.out.println("socket服务器端启动....");
ExecutorService newCachedThreadPool = Executors.newCachedThreadPool();
ServerSocket serverSocket = new ServerSocket(8088);
try {
while (true){
//获取客户端对象
Socket accept = serverSocket.accept();
newCachedThreadPool.execute(new Runnable() {
@Override
public void run() {
try {
InputStream inputStream = accept.getInputStream();
byte[] buf= new byte[1024];
int len=inputStream.read(buf);
String str =new String(buf,0,len);
System.out.println("str:" + str);
//给浏览器反馈数据
OutputStream outputStream = accept.getOutputStream();
outputStream.write("this is my socket - TCP - Test".getBytes());
} catch (IOException e) {
e.printStackTrace();
}
}
});
}
} finally {
serverSocket.close();
}
}
三、使用Lambda优化线程池匿名内部类
这里是个小插曲 以第二部的建立线程代码为例,咋们把建立过程使用lambda替换
注意lambda只存在于 JDK 1.8及以上!
二段代码原文:
newCachedThreadPool.execute(new Runnable() {
@Override
public void run() {
try {
InputStream inputStream = accept.getInputStream();
byte[] buf= new byte[1024];
int len=inputStream.read(buf);
String str =new String(buf,0,len);
System.out.println("str:" + str);
//给浏览器反馈数据
OutputStream outputStream = accept.getOutputStream();
outputStream.write("this is my socket - TCP - Test".getBytes());
} catch (IOException e) {
e.printStackTrace();
}
}
});
使用lambda优化后的代码
newCachedThreadPool.execute(new Thread(()->{
try {
InputStream inputStream = accept.getInputStream();
byte[] buf= new byte[1024];
int len=inputStream.read(buf);
String str =new String(buf,0,len);
System.out.println("str:" + str);
//给浏览器反馈数据
OutputStream outputStream = accept.getOutputStream();
outputStream.write("this is my socket - TCP - Test".getBytes());
} catch (IOException e) {
e.printStackTrace();
}
}));
可以看到代码简洁了不少。
然而更直观点我们可以这样
//Lambda
newCachedThreadPool.execute(new Thread(()->{
System.out.println(1);
}));
//匿名内部类
newCachedThreadPool.execute(new Runnable() {
@Override
public void run() {
System.out.println(1);
}
});