解决:java -jar 在cmd中运行 程序卡顿,卡死的 问题。BIO和NIO案例保存

解决

  • 怎么解决,就是 日志别输出到 cmd 就行了。就行了。就行了。
sh 复制代码
java -jar demo.jar > output.log 2>&1 &
  • 最近写东西,遇到了 程序偶尔卡死的情况。是java -jar 启动的。
  • 具体卡死为:http请求超级卡顿 或 偶尔反应好多个请求,或 tcp Server 粘包,无法收取消息。
  • 直到:我晃了晃 cmd 窗口,最大化,最小化,程序竟然动了,日志又输出了。
  • 终于终于明白了,Window cmd 即要保证正常输出,又要保证性能不卡死你的程序
  • 那你的程序又输出了很多很多日志,那cmd窗口怎么办呢,只有卡死你的程序了。

怀疑流程

  • 因为遇到的是 http请求 和 tcp server 或同时能用,同时不能用,或只能用一个。
  • 怀疑1:是 bio tcp server出现了问题,用了 nio 还一样,疯了。
  • 怀疑2:spring boot 或 spring框架的问题 或 开线程等等问题,最终各种启动 config配置类,配置bean。在 main方法。使用postConstruct 等等等
  • 最后还是没找到问题
java 复制代码
    //ApplicationContext context
    //@PostConstruct
    //@Async
    @EventListener(ApplicationReadyEvent.class)


    /*
    @Component
    public class TcpServerListener implements ApplicationListener<WebServerInitializedEvent> {
        @Autowired
        private UpdateServer updateServer;

        @Override
        public void onApplicationEvent(WebServerInitializedEvent event) {
            //int serverPort = event.getWebServer().getPort();
            // 在此处添加代码以创建和启动 TCP 服务器
            updateServer.startServer(8082);
        }
    }
    */

BIO

java 复制代码
//@Component
public class UpdateServer {

    /*@SpringBootApplication
    public class MyApplication {

        public static void main(String[] args) {
            SpringApplication.run(MyApplication.class, args);
        }

        @EventListener(ApplicationReadyEvent.class)
        public void startServerSocket() throws IOException {
            // 创建ServerSocket并绑定端口
            ServerSocket serverSocket = new ServerSocket(8080);

            // 启动一个新线程来接受客户端连接
            new Thread(() -> {
                while (true) {
                    try {
                        // 接受客户端连接
                        Socket clientSocket = serverSocket.accept();

                        // 处理客户端请求,可以在这里实现自己的逻辑

                        // 关闭客户端连接
                        clientSocket.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }).start();
        }
    }*/


    /*
    @Component
    public class TcpServerListener implements ApplicationListener<WebServerInitializedEvent> {
        @Autowired
        private UpdateServer updateServer;

        @Override
        public void onApplicationEvent(WebServerInitializedEvent event) {
            //int serverPort = event.getWebServer().getPort();
            // 在此处添加代码以创建和启动 TCP 服务器
            updateServer.startServer(8082);
        }
    }
    */


    /**
     * TCP升级网关
     */
    //@Resource
    //private TcpUpdateMapper tcpUpdateMapper;

    /**
     * Redis
     */
    //@Resource
    //private RedisUtil redisUtil;

    //new Thread(() -> { }).start();

    //@PostConstruct
    //@Async
    /*public void startServer() throws Exception {
        //开启TCP Server
        ServerSocket serverSocket = new ServerSocket(8082);
        log.info("服务端打开了 Server started on port {}", 8082);
        while (true) {
            //等待连接
            Socket socket = serverSocket.accept();

            //获取 输入流
            DataInputStream inputStream = new DataInputStream(socket.getInputStream());

            DataOutputStream outputStream = new DataOutputStream(socket.getOutputStream());
            log.info("服务端收到了连接:Accepted connection from client: {}", socket.getInetAddress());
            
            //读取的字节数
            byte[] buffer = new byte[380];//1024
            //真正读取到了多少个
            int bytesRead;
            //循环进行读取
            while ((bytesRead = inputStream.read(buffer)) != -1) {
                //处理二进制数据
                processBinaryData(buffer, bytesRead, socket, outputStream);
            }//循环读取,正常每次都会读取完毕

            inputStream.close();
            outputStream.close();
            socket.close();
        }//死循环接收连接
    }//初始化方法结束*/

    //关闭输入流
    //socket.shutdownInput();
    //关闭输出流,关闭 Socket
    //socket.shutdownOutput();
    //关闭Socket
    //socket.close();

NIO

java 复制代码
@Configuration
public class TcpServerConfig {

    /**
     * TCP升级网关
     */
    @Resource
    private TcpUpdateMapper tcpUpdateMapper;

    /**
     * Redis
     */
    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @Value("${tcp.ip}")
    private String tcpIp;

    //ApplicationContext context
    //@PostConstruct
    //@Async
    @EventListener(ApplicationReadyEvent.class)
    public void startServer() {// throws IOException
        //异步执行
        //ThreadUtil.execAsync(() -> {
        try {
            //打开选择器
            Selector selector = Selector.open();
            //打开通道
            ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
            //非阻塞
            serverSocketChannel.configureBlocking(false);
            //本机IP
            serverSocketChannel.bind(new InetSocketAddress(tcpIp, 8082));
            //进行注册
            serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
            log.info("===============Server started on port 8082===================");

            while (true) {
                //打开通道
                int readyChannels = selector.select();
                //校验下
                if (readyChannels == 0) {
                    continue;
                }
                //获取所有的key
                Set<SelectionKey> selectedKeys = selector.selectedKeys();
                //取得迭代器
                Iterator<SelectionKey> keyIterator = selectedKeys.iterator();
                //如果存在
                while (keyIterator.hasNext()) {
                    //获取这个key
                    SelectionKey key = keyIterator.next();
                    //如果是个连接
                    if (key.isAcceptable()) {
                        //打开这个通道
                        SocketChannel clientSocketChannel = serverSocketChannel.accept();
                        //非阻塞的
                        clientSocketChannel.configureBlocking(false);
                        //注册为可读
                        clientSocketChannel.register(selector, SelectionKey.OP_READ);
                        log.info("收到连接:Accepted connection from: {}", clientSocketChannel.getRemoteAddress());
                    } else if (key.isReadable()) {
                        //如果是可读,获取通道
                        SocketChannel clientSocketChannel = (SocketChannel) key.channel();
                        //读取数量
                        ByteBuffer buffer = ByteBuffer.allocate(38);//1024
                        //真实读取到了多少个
                        int bytesRead = -1;
                        try {
                            //这里报错了,增加防护,如果防护,这个nio就断了
                            bytesRead = clientSocketChannel.read(buffer);
                        } catch (Exception e) {
                            log.info("未读取到");
                            e.printStackTrace();
                        }
                        //未读取到 关闭
                        if (bytesRead == -1) {
                            clientSocketChannel.close();
                        } else if (bytesRead > 0) {
                            //读取到了
                            buffer.flip();
                            //读到这个字节里
                            byte[] data = new byte[bytesRead];
                            buffer.get(data);
                            //处理逻辑
                            processBinaryData(data, bytesRead, clientSocketChannel);
                            //String message = new String(data).trim();
                            //System.out.println("Received message: " + message);

                            //清理
                            buffer.clear();
                        }//读到了
                    }//是可读的
                    //移除key
                    keyIterator.remove();
                }//如果存在
            }//死循环
        } catch (Exception e) {
            e.printStackTrace();
        }
        //}, "MyTcpServerThread").start();
}
java 复制代码
    //有错误,往外层抛
    private void sendUpdateMessage(SocketChannel clientSocketChannel) {
        //去空格
        redisData = redisData.replace(" ", "");
        //转为byte
        byte[] binaryData = hexStringToBytes(redisData);

        //申请字节
        ByteBuffer buffer = ByteBuffer.allocate(binaryData.length);
        //写入
        buffer.put(binaryData);
        buffer.flip();
        //循环写入
        while (buffer.hasRemaining()) {
            try {
                clientSocketChannel.write(buffer);
                log.info("发送了一次升级的消息");
            } catch (IOException e) {
                log.info("发送升级失败");
                e.printStackTrace();
            }
        }
    }
相关推荐
AskHarries2 分钟前
Java字节码增强库ByteBuddy
java·后端
小灰灰__22 分钟前
IDEA加载通义灵码插件及使用指南
java·ide·intellij-idea
夜雨翦春韭25 分钟前
Java中的动态代理
java·开发语言·aop·动态代理
程序媛小果1 小时前
基于java+SpringBoot+Vue的宠物咖啡馆平台设计与实现
java·vue.js·spring boot
追风林1 小时前
mac m1 docker本地部署canal 监听mysql的binglog日志
java·docker·mac
芒果披萨1 小时前
El表达式和JSTL
java·el
duration~2 小时前
Maven随笔
java·maven
zmgst2 小时前
canal1.1.7使用canal-adapter进行mysql同步数据
java·数据库·mysql
跃ZHD2 小时前
前后端分离,Jackson,Long精度丢失
java
blammmp2 小时前
Java:数据结构-枚举
java·开发语言·数据结构