Java使用线程池实现socket编程的方法详解

Java使用线程池实现socket编程的方法详解

简介

Java中的线程池是用来管理和复用线程的工具。线程池可以减少线程的创建和销毁,节省了系统资源。在socket编程中,线程池可以避免创建大量的线程,优化程序性能。

线程池的实现

线程池的创建可以使用Java中的ExecutorExecutorService接口。这两个类都是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技术站

(0)
上一篇 2023年5月23日
下一篇 2023年5月23日

相关文章

  • C++实现考勤管理系统

    C++实现考勤管理系统 简介 考勤管理系统是一种可以对员工的出勤情况进行统计和分析的工具,它可以帮助企业更加有效地管理其员工,并且提高员工出勤率。本文将介绍如何用C++实现考勤管理系统。 设计思路 考勤管理系统需要满足以下功能: 输入员工的考勤信息。 对员工的考勤记录进行存储和管理。 统计员工的出勤情况,并给出相应的报告。 为了实现这些功能,我们需要设计以下…

    C 2023年5月23日
    00
  • C++深入讲解new与deleted关键字的使用

    C++深入讲解new与delete关键字的使用 在C++中,我们可以通过new关键字动态地分配内存,通过delete关键字释放已经分配的内存。new和delete是C++中动态内存管理的必备工具,掌握它们的使用方法对于C++程序员来说至关重要。 本文将详细介绍new和delete的用法以及注意事项。 基本用法 动态分配内存 我们可以使用new关键字从堆中动态…

    C 2023年5月22日
    00
  • C++实现学生信息管理系统

    C++ 实现学生信息管理系统的攻略可以分为以下几个步骤: 1. 界面设计 学生信息管理系统需要一个良好的界面来提供用户友好的使用体验。可以使用如 Qt 等界面框架,或者使用C++标准库提供的基本控制台界面来实现。 2. 数据存储与处理 信息管理系统需要能够存储和处理学生信息,可以选择使用文件、数据库或者数据结构等来完成。 2.1 文件存储 使用文件存储数据是…

    C 2023年5月23日
    00
  • C语言函数封装及变量的作用域

    C语言函数封装及变量的作用域 函数封装 函数封装是指将一段代码打包成函数作为一个单元,使得代码可重用并能提高代码的可读性。在C语言中,可以使用函数的方式实现对代码的封装。 函数的定义与调用 函数的定义分为两步:函数声明和函数实现。 函数声明通常放在头文件中,用于告诉编译器函数的存在,并告知该函数的参数及返回值类型;函数实现则放在源文件中,实现函数的具体功能。…

    C 2023年5月22日
    00
  • vue中ts无法识别引入的vue文件,提示找不到xxx.vue模块的解决

    在Vue项目中使用TypeScript,当我们通过import导入.vue文件时,TS可能会抱怨找不到模块。这是因为TypeScript没有为.vue文件定义类型声明。为了解决这个问题,需要安装”vue-class-component”和”vue-property-decorator”两个库,并对tsconfig.json文件进行一些配置。 以下是具体步骤:…

    C 2023年5月23日
    00
  • 详解C语言之预处理(下)

    下面是“详解C语言之预处理(下)”的完整攻略。 理解C语言中的宏定义 在C语言中,宏定义是一种预处理指令,可以在编译代码前将它们替换为指定的代码片段。这个过程称为宏展开。宏定义的语法格式如下: #define 宏名 宏体 其中,宏名是由字母、数字和下划线组成的标识符,不能以数字开头,而宏体是要替换的代码片段。宏定义还可以带有参数,这种宏定义称为带参数的宏定义…

    C 2023年5月22日
    00
  • C语言实现数字游戏

    C语言实现数字游戏攻略 本文将介绍如何使用C语言编写数字游戏,包括游戏规则、实现步骤和示例代码。 游戏规则 数字游戏的规则如下: 游戏中有一个三位数的目标数字(不能以0开头),玩家需要猜测这个数字。 玩家每次猜测一个三位数,如果该数与目标数字相同,则游戏胜利结束;否则,系统会给出提示: 相同数字的个数和位置(称为“A”)。 相同数字的个数但位置不同(称为“B…

    C 2023年5月23日
    00
  • c语言颜色代码详解

    C语言颜色代码详解 什么是C语言颜色代码 C语言颜色代码指的是在使用C语言开发环境时,代码具有不同颜色的代码块。这种颜色代码通常由开发环境或者编辑器自带,但也可以通过修改配置文件来自定义。 C语言颜色代码的分类 C语言颜色代码通常分为以下几类: 关键字 C语言颜色代码中,关键字通常会使用蓝色或者紫色标注,以示区别。C语言中的关键字包括if, else, wh…

    C 2023年5月24日
    00
合作推广
合作推广
分享本页
返回顶部