Java:每个连接线程阻塞 IO 与 NIO 的完整代码示例?

2023-12-14

好吧,我在这里要疯了。我一直在为我的服务器重写 NIO 代码,并遇到了一些真正令人头痛的问题。最重要的是,让 NIO“正确”是非常困难的。有些人向我推荐了 Rox 教程:http://rox-xmlrpc.sourceforge.net/niotut/,这似乎是一条不错的道路,但并不像我想要的那么完整。例如,我需要知道如何仅在发送排队的传出 ByteBuffer 后关闭服务器端的连接。 SocketChannel.close() 是突然的,如果过早完成可能会丢失数据。我还需要发送大于读取的 ByteBuffer 的大数据包。 Rox 代码(以及我看过的任何其他代码)处理这个问题。还有很多地方似乎没有正确处理未捕获的异常。在我的测试中存在一些错误,考虑到 NIO 的复杂性,尚不清楚如何正确处理它们。

无论如何,当我试图解决这些问题时,更多棘手的微妙之处出现了,而且变得相当复杂。所以我正在考虑一种完全不同的方法。很多人都说 NIO 非常容易出错,而且毫无必要地令人困惑和复杂。他们提倡使用“每个连接一个线程”模型,该模型使用阻塞 IO,其中每个套接字连接都在其自己的线程上运行。这似乎是一个好主意,并且通过为所有连接(如 NIO 中)使用一个选择器线程来减少前端的瓶颈,但代价是更高的开销(对于线程)。这种观点得到了诸如http://paultyma.blogspot.com/2008/03/writing-java-multithreaded-servers.html and http://mailinator.blogspot.com/2008/02/kill-myth-please-nio-is-not-faster-than.html

与 NIO 相比,代码应该很简单,但我真的想要一些示例代码来看看。我似乎找不到任何东西。问题是,我不认为这种“每个连接线程阻塞 I/O”策略有一个更好的名字,我实际上可以得到很好的 Google 结果。任何人都可以将我链接到一些教程或简单的示例来解释使用这种“旧”I/O 方法并使用线程池对其进行扩展吗?或者还有其他至理名言吗?非常感谢!


如果您正在使用 NIO,我还建议使用框架。我一直在与阿帕奇·米娜我会推荐它。

至于阻塞 IO,本质上您将需要一个侦听器线程来接受传入连接并生成额外的线程来处理每个连接。以下是此类侦听器代码的示例,最初贡献给 Apache Felix 项目。 如果您寻找完整但经过修改的版本,您可以在这里浏览源代码.

e.g.

    /*
    * Licensed to the Apache Software Foundation (ASF) under one or more
    * contributor license agreements.  See the NOTICE file distributed with
    * this work for additional information regarding copyright ownership.
    * The ASF licenses this file to You under the Apache License, Version 2.0
    * (the "License"); you may not use this file except in compliance with
    * the License.  You may obtain a copy of the License at
    *
    *      http://www.apache.org/licenses/LICENSE-2.0
    *
        * Unless required by applicable law or agreed to in writing, software
    * distributed under the License is distributed on an "AS IS" BASIS,
    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    * See the License for the specific language governing permissions and
    * limitations under the License.
    */
    package org.apache.felix.shell.remote;
    
    
    import java.io.IOException;
    import java.io.PrintStream;
    import java.net.ServerSocket;
    import java.net.Socket;
    import java.net.SocketException;
    
    
    /**
     * Implements a simple listener that will accept a single connection.
     * <p/>
     *
     * @author Dieter Wimberger (wimpi)
     */
    class Listener
    {
    
        private int m_Port;
        private Thread m_ListenerThread;
        private boolean m_Stop = false;
        private ServerSocket m_ServerSocket;
        private AtomicInteger m_UseCounter;
        private int m_MaxConnections;
    
    
        /**
         * Activates this listener on a listener thread (telnetconsole.Listener).
         */
        public void activate()
        {
            //configure from system property
            try
            {
                m_Port = Integer.parseInt( System.getProperty( "osgi.shell.telnet.port", "6666" ) );
            }
            catch ( NumberFormatException ex )
            {
                Activator.getServices().error( "Listener::activate()", ex );
            }
            try
            {
                m_MaxConnections = Integer.parseInt( System.getProperty( "osgi.shell.telnet.maxconn", "2" ) );
            }
            catch ( NumberFormatException ex )
            {
                Activator.getServices().error( "Listener::activate()", ex );
            }
            m_UseCounter = new AtomicInteger( 0 );
            m_ListenerThread = new Thread( new Acceptor(), "telnetconsole.Listener" );
            m_ListenerThread.start();
        }//activate
    
    
        /**
         * Deactivates this listener.
         * <p/>
         * The listener's socket will be closed, which should cause an interrupt in the
         * listener thread and allow for it to return. The calling thread joins the listener
         * thread until it returns (to ensure a clean stop).
         */
        public void deactivate()
        {
            try
            {
                m_Stop = true;
                //wait for the listener thread
                m_ServerSocket.close();
                m_ListenerThread.join();
            }
            catch ( Exception ex )
            {
                Activator.getServices().error( "Listener::deactivate()", ex );
            }
        }//deactivate
    
        /**
         * Class that implements the listener's accept logic as a <tt>Runnable</tt>.
         */
        private class Acceptor implements Runnable
        {
    
            /**
             * Listens constantly to a server socket and handles incoming connections.
             * One connection will be accepted and routed into the shell, all others will
             * be notified and closed.
             * <p/>
             * The mechanism that should allow the thread to unblock from the ServerSocket.accept() call
             * is currently closing the ServerSocket from another thread. When the stop flag is set,
             * this should cause the thread to return and stop.
             */
            public void run()
            {
                try
                {
                    /*
                        A server socket is opened with a connectivity queue of a size specified
                        in int floodProtection.  Concurrent login handling under normal circumstances
                        should be handled properly, but denial of service attacks via massive parallel
                        program logins should be prevented with this.
                    */
                    m_ServerSocket = new ServerSocket( m_Port, 1 );
                    do
                    {
                        try
                        {
                            Socket s = m_ServerSocket.accept();
                            if ( m_UseCounter.get() >= m_MaxConnections )
                            {
                                //reject with message
                                PrintStream out = new PrintStream( s.getOutputStream() );
                                out.print( INUSE_MESSAGE );
                                out.flush();
                                //close
                                out.close();
                                s.close();
                            }
                            else
                            {
                                m_UseCounter.increment();
                                //run on the connection thread
                                Thread connectionThread = new Thread( new Shell( s, m_UseCounter ) );
                                connectionThread.start();
                            }
                        }
                        catch ( SocketException ex )
                        {
                        }
                    }
                    while ( !m_Stop );
    
                }
                catch ( IOException e )
                {
                    Activator.getServices().error( "Listener.Acceptor::activate()", e );
                }
            }//run
    
        }//inner class Acceptor
    
        private static final String INUSE_MESSAGE = "Connection refused.\r\n"
            + "All possible connections are currently being used.\r\n";
    
    }//class Listener

你可以找到其他例子here and here.

请注意,当负载较多时,NIO 相对于阻塞模型的优势就会发挥出来。从某一点开始,线程创建、管理和上下文切换的额外工作量将限制您的系统性能。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Java:每个连接线程阻塞 IO 与 NIO 的完整代码示例? 的相关文章

  • 通过SOCKS代理连接Kafka

    我有一个在 AWS 上运行的 Kafka 集群 我想用标准连接到集群卡夫卡控制台消费者从我的应用程序服务器 应用程序服务器可以通过 SOCKS 代理访问互联网 无需身份验证 如何告诉 Kafka 客户端通过代理进行连接 我尝试了很多事情 包
  • 在不支持线程的程序加载的共享库中使用 C++11 多线程

    我目前正在尝试在共享库中使用 C 11 多线程 该库加载到 Linux 上的主程序 用 C 编写 中 这是一个大型模拟程序的一部分 我无法更改有关库加载的任何内容或更改一般的主程序 主程序是用 gcc 4 1 2 编译的 我没有它的源代码
  • 使用 GWT 读取非常大的本地 XML 文件

    我正在使用 GWT 构建我的第一个 Java 应用程序 它必须从一个非常大的 XML 文件中读取数据 当我尝试发送对文件中信息的请求时遇到问题 并且我不太确定它是否与文件的大小或我的语义有关 在我的程序中 我有以下内容 static fin
  • 是否有任何简单(且最新)的 Java 框架可用于在 Swing 应用程序中嵌入电影?

    我正在构建一个小型 Swing 应用程序 我想在其中嵌入一部电影 重要的是 这个应用程序是一个 WebStart 应用程序 并且该库应该能够打包在我启动的 jnlp 中 即 不依赖于本机库 我知道并尝试过 JMF 但我认为与其他框架相比 其
  • Spring Data JPA 选择不同

    我有一个情况 我需要建立一个select distinct a address from Person a 其中地址是 Person 内的地址实体 类型的查询 我正在使用规范动态构建我的 where 子句并使用findAll Specifi
  • Spring Boot自动装配存储库始终为空[重复]

    这个问题在这里已经有答案了 每次我进入我的服务类时 存储库似乎都没有自动连接 因为它不断抛出 NullPointerException 谁能帮我检查一下我缺少什么吗 这是我的代码 演示应用程序 java package com exampl
  • 通往楼梯顶部的可能路径

    这是一个非常经典的问题 我听说谷歌在他们的面试中使用过这个问题 问题 制定一个递归方法 打印从楼梯底部到楼梯顶部的所有可能的独特路径 有 n 个楼梯 您一次只能走 1 步或 2 步 示例输出 如果它是一个有 3 级楼梯的楼梯 1 1 1 2
  • Jackson XML ArrayList 输出具有两个包装器元素

    我在 Jackson 生成的 XML 输出中得到了两个包装器元素 我只想拥有一个 我有一个 Java bean Entity Table name CITIES JacksonXmlRootElement localName City pu
  • Java Swing For mac 中的 DJ Native Swing 浏览器

    我有一个用 Swing 制作的 Java 应用程序 并且使用了一个 DJ Native Swing 浏览器 当我尝试在 OS X 上使用它时 它抛出了一个NoClassDefFoundError尽管我添加了 swt jar 但始终如此 有人
  • Java:如何为山区时间创建 TimeZone 对象?

    必须不禁用夏令时 嗯 在这个清单 http en wikipedia org wiki List of tz database time zones在 zoneinfo 时区名称中 有很多声称是 山地时间 找到最适合您想要的那个 然后使用它
  • 了解joda时间PeriodFormatter

    我以为我明白了 但显然我不明白 你能帮我通过这些单元测试吗 Test public void second assertEquals 00 00 01 OurDateTimeFormatter format 1000 Test public
  • 流中的非终结符 forEach() ?

    有时 在处理 Java Stream 时 我发现自己需要一个非终端 forEach 来触发副作用但不终止处理 我怀疑我可以用 map item gt f item 之类的方法来做到这一点 其中方法 f 执行副作用并将项目返回到流中 但这似乎
  • 在 SWT/JFace RCP 应用程序中填充巨大的表

    您将如何在 SWT 表中显示大量行 巨大是指超过 20K 行 20 列的东西 不要问我为什么需要展示那么多数据 这不是重点 关键是如何让它尽可能快地工作 这样最终用户就不会厌倦等待 每行显示某个对象的实例 列是其属性 一些 我想使用 JFa
  • java库维护数据库结构

    我的应用程序一直在开发 所以偶尔 当版本升级时 需要创建 更改 删除一些表 修改一些数据等 通常需要执行一些sql代码 是否有一个 Java 库可用于使我的数据库结构保持最新 通过分析类似 db structure version 信息并执
  • 返回 Java 8 中的通用函数接口

    我想写一种函数工厂 它应该是一个函数 以不同的策略作为参数调用一次 它应该返回一个函数 该函数根据参数选择其中一种策略 该参数将由谓词实现 嗯 最好看看condition3为了更好的理解 问题是 它没有编译 我认为因为编译器无法弄清楚函数式
  • 是否可以使用 Java Guava 将函数应用于集合?

    我想使用 Guava 将函数应用于集合 地图等 基本上 我需要调整 a 的行和列的大小Table分别使所有行和列的大小相同 执行如下操作 Table
  • “无法实例化活动”错误

    我的一个 Android 应用程序拥有大约 100 000 个用户 每周大约 10 次 我会通过 Google 的市场工具向我报告以下异常情况 java lang RuntimeException Unable to instantiate
  • Spring-ws:如何从没有“Request”元素的 xsd 创建 Wsdl

    尝试为客户端实现 SOAP Web 服务 我需要一个 wsdl 文件来通过soapUI 测试该服务 但正如您在下面看到的 这个 xsd 没有 Request 和 Response 方法 所有请求和响应都被定义为基本 ServiceProvi
  • 将 Apache Camel 执行器指标发送到 Prometheus

    我正在尝试转发 添加 Actuator Camel 指标 actuator camelroutes 将交换 交易数量等指标 发送到 Prometheus Actuator 端点 有没有办法让我配置 Camel 将这些指标添加到 Promet
  • 泛型、数组和 ClassCastException

    我想这里一定发生了一些我不知道的微妙事情 考虑以下 public class Foo

随机推荐

  • Java 数据库连接

    我有一个java项目 其中有许多连接到数据库的文件 谁能告诉我是否可以使用 java 类文件连接到数据库 这样我就不会为每个文件创建数据库连接 请教我如何操作 感谢您的帮助 D 这是我使用的代码 但它不起作用 dbConnect java
  • 在 Django 中,如何向用户发送登录后消息?

    我有一个 Django 网站 当用户登录时 我会向他们显示一条成功消息 我使用如下信号来执行此操作 def post login actions sender user request kwargs messages success req
  • 使用 OpenSL 进行通话录音

    自从 Galaxy S5 中的棒棒糖更新后 我尝试修复应用程序中的通话录音 作为基础 我使用这里的谷歌示例项目 Sample 这是代码的主要部分 AudioRecorder AudioRecorder SampleFormat sample
  • 使用D3多次更新表不起作用

    我有一个页面需要加载新数据并使用 d3 将其更新为现有表元素 我正在写以下内容但没有用 completeTableData head1 va1 head2 val2 haed1 val4 head2 val5 var tr d3 selec
  • Android 上的新电子邮件通知

    有没有办法让应用程序在收到新电子邮件时收到通知 我的目标是 如果收到具有特定主题的电子邮件 将其视为 过滤器 或 规则 则发出警报 播放声音 振动等 但我不想检查电子邮件我自己做服务器 我想我正在寻找类似 android telephony
  • 如何在android中从图库中选择多张图像?

    我正在制作一个项目 我想从图库中选择多张照片并将其保存在图像视图数组中 我可以导入单个图像并保存在 imageview 谁能告诉我如何导入多个图像并保存在数组或不同的图像视图中 MainActivity extends Activity i
  • 点击式 tkinter 窗口

    该函数复制自使用 TkInter 绑定设置不可交互 点击 覆盖 不仅窗口无法点击 PNG 也不透明 PNG在这里 https drive google com file d 1tlLl2hjPq38mc c PpMhkKDlP1HqvDY5
  • 加速插值练习

    我正在对大约 120 万个观测值运行大约 45 000 个局部线性回归 本质上 所以我希望得到一些帮助来加快速度 因为我很不耐烦 我基本上是在尝试为一堆公司构建逐年的工资合同 工资函数 给定公司 年份 职位的经验 这是我正在使用的数据集 基
  • 将字段值连接到 SQL Server 中的字符串

    我需要一个与Oracle类似的功能WM CONCAT在 SQL Server 中 它返回一个逗号分隔的列表 其中包含您作为参数传递的任何字段 例如 在 Oracle 中 select WM CONCAT first name from em
  • Visual Studio 中“ID 为 #### 的进程未运行”

    我尝试在 Visual Studio 2013 update 3 上运行任何程序 并收到以下警告框 ID 为 的进程未运行 每次都会显示不同的身份证号码 在错误窗口中 我收到以下错误消息 程序 3148 iisexpress exe 已退出
  • 在当前日期中添加一年 PYTHON

    我已经取了一个date from database与以下variable i operation date 我得到了这样的值 April 1 2013 我需要在上面加上一年 这样我就可以得到 April 1 2014 请建议 我该怎么做 A
  • Oracle SYS_REFCURSOR 无法用作返回类型

    我需要使用 oracle 11g 中的成员函数提取并显示 db 中所有记录的所有年份 CREATE or replace TYPE BODY student t AS MEMBER FUNCTION getYear RETURN SYS R
  • 通过使用键作为值来反序列化 Jackson

    我有一个与此类似的 JSON 结构 teams team1Id team1Name team2Id team2Name 我想将其反序列化为这些 Java 类 class Teams Team team1 Team team2 class T
  • 使用 AVPlayer 和 AVMutableComposition 的声音播放未对齐

    我正在尝试使用多个乐器样本创建一首歌曲AV合成 当我播放两个声音资源时kCMTimeZero in an AVMutableComposition 我希望他们同时玩 但有一个非常轻微的偏移 这种情况只发生在第一次玩游戏时 所以这似乎是某种加
  • python 中变量的 ast.literal_eval ?

    假设我有一个文件example py 导入示例 VVV 2 DictionaryNameB a VVV bb SomethingB c False ccc None dddd true eeeee 0 123456 f 2 h 1 2 3
  • Android NestedScrollView 在 ListView 中仅显示一项

    有人知道我的布局有什么问题吗 我无法弄清楚为什么我的 ListView 只显示一项 布局 xml
  • 修改重复序列中的单个事件不会反映在从 Rest API 读取的数据中

    当您在 Office365 Outlook 中创建正在发生的事件并修改任何单个事件 编辑事件 时 更改永远不会反映在 REST API 使用的数据中 不会创建重复异常 新事件 并且系列主数据没有更改任何单个字段 预期的行为是 SeriesM
  • 虚拟环境中的 Pip 升级访问被拒绝

    Windows 10 python 3 9 13 以管理员身份在命令提示符下 我开始学习tensorflow 并按照他们网站上的步骤进行操作 当我尝试在虚拟环境中使用命令 pip install upgrade pip 时 它显示以下消息
  • python 线程块

    我正在尝试编写一个程序 该程序在循环中创建新线程 并且不等待它们完成 据我了解 如果我使用 start 在线程上 我的主循环应该继续 另一个线程将关闭并同时完成其工作 然而 一旦我的新线程启动 循环就会阻塞 直到线程完成 我是否误解了Pyt
  • Java:每个连接线程阻塞 IO 与 NIO 的完整代码示例?

    好吧 我在这里要疯了 我一直在为我的服务器重写 NIO 代码 并遇到了一些真正令人头痛的问题 最重要的是 让 NIO 正确 是非常困难的 有些人向我推荐了 Rox 教程 http rox xmlrpc sourceforge net nio