2023-分布式学习记录5

并发服务技术

本节介绍三种并发请求处理技术,即多线程、线程池、事件驱动,同时介绍部分使用 java 需要注意的东西。

线程

线程的定义及特点

  • 不同的线程在逻辑上相互独立地并行地执行
  • 每个的线程都拥有自己独立的运行上下文(Runtime Context),主要包括独立的内存栈(主要存放局部变量和函数参数)和独立的CPU寄存器状态。每个线程可以不受干扰的访问自己的局部变量
  • 属于同一个进程的多个线程共享该进程的内存地址空间
  • 每一个线程都有自己的“主函数”。线程启动后,其主函数开始执行;线程主函数执行完毕,线程的生命周期就结束了

Java 的线程对象

  • Java 线程对象是对操作系统线程对象的一个封装
  • 一个Java线程对象一般都是 Thread 类(JDK实现的基类)的子类。子类需要重载 run 函数,作为自己的线程主函数

基于多线程的并发服务技术

// 多线程
// 1. 重载 Thread 类
public class UDPThread extends Thread {

    DatagramSocket asocket = null;
    DatagramPacket request = null;

    public UDPThread(DatagramSocket asocket, DatagramPacket request) {
        this.asocket = asocket;
        this.request = request;
    }
    // 重载 run 函数
    public void run() {
        try {
            // 创建数据报
            DatagramPacket reply = new DatagramPacket(request.getData(), request.getLength(), request.getAddress(),
                    request.getPort());
            // 发送数据报
            asocket.send(reply);
        } catch (SocketException e) {
            System.out.println("Socket: " + e.getMessage());
        } catch (IOException e) {
            System.out.println("IO: " + e.getMessage());
        }
    }
}
// 2. 遇到新任务时创建新线程进行处理
public class MultiThreadUDPServer {
    public static void main(String args[]) throws Exception {
        DatagramSocket aSocket = new DatagramSocket(6789);
        int count = 0;
        while (true) {
            byte[] buffer = new byte[1000];
            DatagramPacket request = new DatagramPacket(buffer, buffer.length);
            // 接收数据
            aSocket.receive(request);
            System.out.println("Message from Client: " + new String(request.getData()));
            count++;
            // 创建新线程
            UDPThread serverThread = new UDPThread(aSocket, request);
            // 启动线程
            serverThread.start();
        }
    }
}
// 多线程
// 1. 重载 Thread 类
public class UDPThread extends Thread {

    DatagramSocket asocket = null;
    DatagramPacket request = null;

    public UDPThread(DatagramSocket asocket, DatagramPacket request) {
        this.asocket = asocket;
        this.request = request;
    }
    // 重载 run 函数
    public void run() {
        try {
            // 创建数据报
            DatagramPacket reply = new DatagramPacket(request.getData(), request.getLength(), request.getAddress(),
                    request.getPort());
            // 发送数据报
            asocket.send(reply);
        } catch (SocketException e) {
            System.out.println("Socket: " + e.getMessage());
        } catch (IOException e) {
            System.out.println("IO: " + e.getMessage());
        }
    }
}
// 2. 遇到新任务时创建新线程进行处理
public class MultiThreadUDPServer {
    public static void main(String args[]) throws Exception {
        DatagramSocket aSocket = new DatagramSocket(6789);
        int count = 0;
        while (true) {
            byte[] buffer = new byte[1000];
            DatagramPacket request = new DatagramPacket(buffer, buffer.length);
            // 接收数据
            aSocket.receive(request);
            System.out.println("Message from Client: " + new String(request.getData()));
            count++;
            // 创建新线程
            UDPThread serverThread = new UDPThread(aSocket, request);
            // 启动线程
            serverThread.start();
        }
    }
}

 

基于线程池的并发服务技术

// 线程池
public ThreadPoolExecutor(int corePoolSize, int maximunPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler);
/*
corePoolSize,核心线程数。
没有任务时,核心线程也一直存活;所需线程数小于核心线程数时,线程池也会创建新线程;设置allowCoreThreadTimeout=true时,核心线程会超时关闭

maximunPoolSize,最大线程数
当线程数=maxPoolSize,且任务队列已满,此时添加任务时会触发RejectedExecutionHandler进行处理

keepAliveTime,线程空闲时间
如果线程数>corePoolSize,且有线程空闲时间达到keepAliveTime时,线程会销毁,直到线程数量=corePoolSize;如果设置allowCoreThreadTimeout=true时,核心线程执行完任务也会销毁直到数量=0

workQueue,任务队列
*/

public class ThreadPoolServer {
    public static void main(String[] args) throws Exception {
        // 创建线程池
        ThreadPoolExecutor executor = new ThreadPoolExecutor(5, 10, 200, TimeUnit.MILLISECONDS,
                new ArrayBlockingQueue<Runnable>(5));
        ServerSocket listenSocket = new ServerSocket(8189); // 创建监听端口
        Socket socket = null; // 记录连接端口
        int count = 0;
        System.out.println("Server listening at 8189");
        while (true) {
            socket = listenSocket.accept(); // 从队列中获取端口
            count++; // 计数
            MyTask myTask = new MyTask(socket,count); // 建立新线程
            executor.execute(myTask); // 执行
        }
    }
}

class MyTask implements Runnable {
    private Socket socket = null;
    private int num = 0;

    public MyTask(Socket socket, int num) {
        this.socket = socket;
        this.num = num;
    }
    // 重载 run 函数
    @Override
    public void run() {
        InputStream is = null;
        InputStreamReader isr = null;
        BufferedReader br = null;
        OutputStream os = null;
        PrintWriter pw = null;
        try {
            is = socket.getInputStream();
            isr = new InputStreamReader(is);
            br = new BufferedReader(isr);
            os = socket.getOutputStream();
            pw = new PrintWriter(os);
            String info = null;
            while ((info = br.readLine()) != null) {
                System.out.println("Thread" + num + ",Message from client:" + info);
                pw.println(info);
                pw.flush();
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (pw != null)
                    pw.close();
                if (os != null)
                    os.close();
                if (br != null)
                    br.close();
                if (isr != null)
                    isr.close();
                if (is != null)
                    is.close();
                if (socket != null)
                    socket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

 

posted @ 2023-03-06 01:52  kuaiquxie  阅读(7)  评论(0编辑  收藏  举报