Java使用线程池实现socket编程的方法详解
简介
Java中的线程池是用来管理和复用线程的工具。线程池可以减少线程的创建和销毁,节省了系统资源。在socket编程中,线程池可以避免创建大量的线程,优化程序性能。
线程池的实现
线程池的创建可以使用Java中的Executor或ExecutorService接口。这两个类都是Executor框架的一部分,提供了管理线程池和执行线程任务的方法。
下面是一个创建线程池的示例代码:
ExecutorService executor = Executors.newFixedThreadPool(10);
创建的是一个固定大小的线程池,大小为10。根据实际需求,也可以创建单线程池、缓存线程池和可变尺寸线程池。
socket编程与线程池的结合
下面是一个简单的socket编程示例,接收客户端请求并返回信息:
public class Server {
public static void main(String[] args) throws Exception {
ServerSocket serverSocket = new ServerSocket(8888);
System.out.println("服务端启动完成,等待客户端请求...");
while (true) {
Socket socket = serverSocket.accept();
System.out.println("接收到客户端请求:" + socket.getInetAddress().getHostAddress() + ":" + socket.getPort());
InputStream inputStream = socket.getInputStream();
byte[] buf = new byte[1024];
int length = inputStream.read(buf);
String request = new String(buf, 0, length);
System.out.println("接收到客户端请求:" + request);
OutputStream outputStream = socket.getOutputStream();
outputStream.write("Hello World!".getBytes());
outputStream.flush();
outputStream.close();
inputStream.close();
socket.close();
}
}
}
这是一个简单的服务端代码,使用ServerSocket监听端口8888,接收客户端请求并返回信息。
如果仅使用上面的代码,每当有一个客户端连接上来,就会创建一个新的线程来处理请求。如果客户端请求很频繁,就会导致线程创建和销毁的频繁操作,浪费系统资源。
使用线程池来优化代码,只需要将核心代码包装在Runnable
接口中,提交给线程池执行即可,如下:
public class Server {
public static void main(String[] args) throws Exception {
ServerSocket serverSocket = new ServerSocket(8888);
System.out.println("服务端启动完成,等待客户端请求...");
ExecutorService executor = Executors.newFixedThreadPool(10);
while (true) {
Socket socket = serverSocket.accept();
System.out.println("接收到客户端请求:" + socket.getInetAddress().getHostAddress() + ":" + socket.getPort());
executor.submit(new Handler(socket));
}
}
}
class Handler implements Runnable {
private Socket socket;
public Handler(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
try {
InputStream inputStream = socket.getInputStream();
byte[] buf = new byte[1024];
int length = inputStream.read(buf);
String request = new String(buf, 0, length);
System.out.println("接收到客户端请求:" + request);
OutputStream outputStream = socket.getOutputStream();
outputStream.write("Hello World!".getBytes());
outputStream.flush();
outputStream.close();
inputStream.close();
socket.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
上面的代码将核心代码封装到Handler
类中,并且通过创建线程池的方式来使用线程池,对客户端请求进行处理。
多线程socket编程示例
下面是一个多线程socket编程的示例,客户端连接成功后,传输文件到服务端:
服务端代码:
public class Server {
public static void main(String[] args) throws Exception {
ServerSocket serverSocket = new ServerSocket(8888);
System.out.println("服务端启动完成,等待客户端请求...");
ExecutorService executor = Executors.newFixedThreadPool(10);
while (true) {
Socket socket = serverSocket.accept();
System.out.println("接收到客户端请求:" + socket.getInetAddress().getHostAddress() + ":" + socket.getPort());
executor.submit(new Handler(socket));
}
}
}
class Handler implements Runnable {
private Socket socket;
public Handler(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
try {
InputStream inputStream = socket.getInputStream();
byte[] buf = new byte[1024];
int length = inputStream.read(buf);
String request = new String(buf, 0, length);
if (request.equalsIgnoreCase("file")) {
System.out.println("请求传输文件");
length = inputStream.read(buf);
String fileName = new String(buf, 0, length);
System.out.println("文件名:" + fileName);
OutputStream outputStream = new FileOutputStream(fileName);
while ((length = inputStream.read(buf)) != -1) {
outputStream.write(buf, 0, length);
}
System.out.println("传输完成");
outputStream.close();
} else {
System.out.println("接收到客户端请求:" + request);
OutputStream outputStream = socket.getOutputStream();
outputStream.write("Hello World!".getBytes());
outputStream.flush();
outputStream.close();
}
inputStream.close();
socket.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
客户端代码:
public class Client {
public static void main(String[] args) throws Exception {
Socket socket = new Socket("localhost", 8888);
OutputStream outputStream = socket.getOutputStream();
Scanner scanner = new Scanner(System.in);
System.out.println("输入文件名发送文件,否则发送字符串");
String input = scanner.nextLine();
if (isFile(input)) {
outputStream.write("file".getBytes());
outputStream.flush();
outputStream.write(input.getBytes());
outputStream.flush();
InputStream inputStream = new FileInputStream(input);
byte[] buf = new byte[1024];
int length;
while ((length = inputStream.read(buf)) != -1) {
outputStream.write(buf, 0, length);
}
inputStream.close();
outputStream.flush();
outputStream.close();
} else {
outputStream.write(input.getBytes());
outputStream.flush();
InputStream inputStream = socket.getInputStream();
byte[] buf = new byte[1024];
int length = inputStream.read(buf);
String response = new String(buf, 0, length);
System.out.println(response);
inputStream.close();
outputStream.close();
}
socket.close();
}
private static boolean isFile(String input) {
try {
File file = new File(input);
if (file.isFile()) {
return true;
}
return false;
} catch (Exception e) {
return false;
}
}
}
上面的代码中,如果客户端输入的是文件名,则客户端向服务端发送"file"请求,并传输文件到服务端;否则客户端向服务端发送普通字符串请求,服务端返回"Hello World!"。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java使用线程池实现socket编程的方法详解 - Python技术站