4.23学习总结

一.NIO(一)

(一).简介:

NIO 是 Java SE 1.4 引入的一组新的 I/O 相关的 API,它提供了非阻塞式 I/O、选择器、通道、缓冲区等新的概念和机制。相比与传统的 I/O 多出的 N 不是单纯的 New,更多的是代表了 Non-blocking 非阻塞,NIO具有更高的并发性、可扩展性以及更少的资源消耗等优点。

(二).NIO 与传统BIO:

NIO:是同步非阻塞的,服务器实现模式为 一个线程处理多个连接。服务端只会创建一个线程负责管理Selector(多路复用器),Selector(多路复用器)不断的轮询注册其上的Channel(通道)中的 I/O 事件,并将监听到的事件进行相应的处理。每个客户端与服务端建立连接时会创建一个 SocketChannel 通道,通过 SocketChannel 进行数据交互。

BIO:全称是Blocking IO,同步阻塞式IO,是JDK1.4之前的传统IO模型,服务器实现模式为一个连接一个线程。每当客户端有连接请求时服务器端就需要启动一个线程进行处理。

两者主要区别如下:

  • 阻塞和非阻塞:NIO 使用非阻塞式 I/O,而 BIO 使用阻塞式 I/O。在阻塞式 I/O 中,当一个 I/O 操作完成之前,线程会一直被阻塞,直到 I/O 操作完成;在非阻塞式 I/O 中,线程可以继续执行其他任务,直到 I/O 操作完成并返回结果。
  • 线程模型:NIO 中的线程模型是基于事件驱动的,当一个 I/O 操作完成时,会触发相应的事件通知线程处理;而在 BIO 中,每个线程都负责处理一个客户端连接,需要不断地轮询客户端的输入输出流,以便及时响应客户端的请求。
  • 内存消耗:NIO 中使用的缓冲区(Buffer)可以重复利用,减少了频繁的内存分配和回收,从而减少了内存的消耗;而在 BIO 中,每个客户端连接都需要单独分配一个缓冲区,容易造成内存的浪费。
  • 并发性能:NIO 中使用非阻塞式 I/O,可以同时处理多个客户端连接,从而提高了并发处理能力;而在 BIO 中,由于每个客户端连接都需要一个线程来处理,当连接数量增加时,容易出现线程饥饿和资源耗尽的问题。

 

(三).NIO的核心原理

 

 工作流程:

  • 创建 Selector:Selector 是 NIO 的核心组件之一,它可以同时监听多个通道上的 I/O 事件,并且可以通过 select() 方法等待事件的发生。
  • 注册 Channel:通过 Channel 的 register() 方法将 Channel 注册到 Selector 上,这样 Selector 就可以监听 Channel 上的 I/O 事件。
  • 等待事件:调用 Selector 的 select() 方法等待事件的发生,当有事件发生时,Selector 就会通知相应的线程进行处理。
  • 处理事件:根据不同的事件类型,调用对应的处理逻辑。
  • 关闭 Channel:当 Channel 不再需要使用时,需要调用 Channel 的 close() 方法关闭 Channel,同时也需要调用 Buffer 的 clear() 方法清空 Buffer 中的数据,以释放内存资源。

 

 二.java聊天室控制台实现公聊私聊

其私聊核心思路就是hashmap将每个人的id(用户名)和其对应的输出流,形成键值对,存到hashmap中,在需要的时候,直接根据用户名就可以调出其对应的输出流.

公聊的核心思路在于使用ArrayList集合,将所有用户的输出流都存入集合中,然后遍历对每个用户进行输出.

实例代码:

客户端:

public class Client {
    public static void main(String[] args) {
        //连接服务器
        try {
            System.out.println("连接服务端");
            Socket socket = new Socket("localhost",8088);
            System.out.println("连接服务端成功");
            Thread t1 = new Thread(new ClientWriteData(socket));
            Thread t2 = new Thread(new ClientReadData(socket));
            t1.start();
            t2.start();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
class ClientWriteData implements Runnable{
    private Scanner scan;
    private Socket socket;
    public ClientWriteData(Socket socket){
        this.socket = socket;
    }
    public void run(){
        try {
            OutputStream out = socket.getOutputStream();
            OutputStreamWriter osw;osw = new OutputStreamWriter(out,"GBK");
            PrintWriter pw = new PrintWriter(osw,true);
            System.out.println("请输入用户名:");
            scan = new Scanner(System.in);
            String str0 = scan.next();
            pw.println(str0);
            while(true){
                System.out.println("请选择私聊或者群发:1表示私聊\t2表示群发");
                int n = scan.nextInt();
                pw.println(n);
                switch(n){
                    case 1:
                        System.out.println("请输入私聊对象: ");
                        String name = scan.next();
                        pw.println(name);
                        System.out.println("私聊的信息:");
                        String str = scan.next();
                        pw.println(str);
                        break;
                    case 2:
                        System.out.println("请输入群发消息:");
                        System.out.println(str0+"正在发消息:");
                        String str1 = scan.next();
                        pw.println(str1);
                        break;
                    default:
                        System.out.println("退出消息发送:");
                        System.exit(0);
                }

            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
class ClientReadData implements Runnable{
    private Socket socket;
    public ClientReadData(Socket socket){
        this.socket = socket;
    }
    public void run(){
        try {
            InputStream is = socket.getInputStream();
            InputStreamReader isr = new InputStreamReader(is,"GBK");
            BufferedReader br = new BufferedReader(isr);
            String str = null;
            while((str = br.readLine())!=null){
                System.out.println(str);
            }
        } catch (IOException e) {
            System.err.println("服务端已断开!!!");
            e.printStackTrace();
        }
    }
}

服务端:

public class Server {
    //群发
    //定义一个集合,用于存储所有客户端的输出流
    List<PrintWriter> allPw = new ArrayList<>();
    //用于根据用户名存储客户端输出流
    Map<String,PrintWriter> map = new HashMap();
    //创建线程池对象
    //ExecutorService pool = Executors.newCachedThreadPool();
    public static void main(String[] args) {
        try {
            //向系统申请端口号 端口号是系统中所有程序没有使用过的端口,才能使用成功
            //端口号的范围:0-65535之间 0-1023之间是系统端口
            ServerSocket server = new ServerSocket(8088);
            System.out.println("服务端开启成功!!!");
            Server s = new Server();
            while(true){
                System.out.println("等待客户端连接:");
                //阻塞方法 accept():等待客户端的连接
                Socket accept = server.accept();
                System.out.println("和客户端连接成功!!!");
                //获取IP地址
                InetAddress address = accept.getInetAddress();
                String ip = address.getHostAddress();
                System.out.println(ip);
                Thread t = new Thread(s.new ClientHandler(accept));
                t.start();
            }

        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    class ClientHandler implements Runnable{
        private Socket socket;
        public ClientHandler(Socket socket){
            this.socket = socket;
        }
        public void run(){
            try{
                InputStream is = socket.getInputStream();
                InputStreamReader isr = new InputStreamReader(is,"GBK");
                BufferedReader br = new BufferedReader(isr);

                OutputStream os = socket.getOutputStream();
                OutputStreamWriter osw = new OutputStreamWriter(os,"GBK");
                PrintWriter pw = new PrintWriter(osw,true);
                //一个客户端连接服务器,则把输出流存入到集合中
                String str = null;
                //用户名
                String name = br.readLine();
                allPw.add(pw);
                map.put(name, pw);
                while((str = br.readLine())!=null){
                    if(str.equals("1")){//私聊工作
                        //需要私聊的对象
                        str = br.readLine();
                        //私聊对象的输出流
                        PrintWriter p = map.get(str);
                        str = br.readLine();
                        p.println(str);
                    }else{//群发

                        System.out.println("");
                        str = br.readLine();
                        for(PrintWriter p:allPw){
                            if(p == pw){
                                continue;
                            }
                            p.println(str);
                        }
                    }
                }
            }catch(IOException e){
                e.printStackTrace();
            }
        }
    }
}

相关推荐

  1. 学习总结

    2024-04-24 00:12:04       16 阅读
  2. 学习总结

    2024-04-24 00:12:04       15 阅读
  3. 学习总结

    2024-04-24 00:12:04       15 阅读
  4. 学习总结

    2024-04-24 00:12:04       12 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-04-24 00:12:04       19 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-04-24 00:12:04       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-04-24 00:12:04       19 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-04-24 00:12:04       20 阅读

热门阅读

  1. php中常见的正则使用方法

    2024-04-24 00:12:04       12 阅读
  2. Thinkphp命令行创建repository和transform层扩展包

    2024-04-24 00:12:04       13 阅读
  3. 多特征融合的聚类背景下特征选择问题笔记整理

    2024-04-24 00:12:04       16 阅读
  4. 【Git 】常用指令

    2024-04-24 00:12:04       11 阅读
  5. Web集群_01

    2024-04-24 00:12:04       13 阅读
  6. Python实战:文本内容提取

    2024-04-24 00:12:04       15 阅读
  7. Chapter 1-14. Introduction to Congestion in Storage Networks

    2024-04-24 00:12:04       15 阅读
  8. 成长&工作&思考

    2024-04-24 00:12:04       12 阅读
  9. g 对象:Flask 应用中的“临时口袋”

    2024-04-24 00:12:04       13 阅读
  10. 给rwkv_pytorch配了个流式服务和请求demo

    2024-04-24 00:12:04       14 阅读