Java 8非阻塞读取是否存在争用条件?

Java 8非阻塞读取是否存在争用条件?,java,multithreading,tcp,java-8,nonblocking,Java,Multithreading,Tcp,Java 8,Nonblocking,现在这个问题困扰了我一段时间 在我工作的一个工作应用程序中,我在非阻塞模式下使用SocketChannel与嵌入式设备通信。 现在,我收到了零星损坏的数据。 在某些个人电脑上它不会发生,现在它发生在我的电脑上。 但当我在程序中更改太多时,问题就消失了 这么多可能会产生影响。时间,网络接口硬件,win7,java版本,公司防火墙 数据读取归结为以下代码: byteBuffer.compact(); socketChannel.read(byteBuffer); // <<< pr

现在这个问题困扰了我一段时间

在我工作的一个工作应用程序中,我在非阻塞模式下使用SocketChannel与嵌入式设备通信。 现在,我收到了零星损坏的数据。 在某些个人电脑上它不会发生,现在它发生在我的电脑上。 但当我在程序中更改太多时,问题就消失了

这么多可能会产生影响。时间,网络接口硬件,win7,java版本,公司防火墙

数据读取归结为以下代码:

byteBuffer.compact();
socketChannel.read(byteBuffer); // <<< problem here ?
byteBuffer.flip();
if( byteBuffer.hasRemaining() ){
    handleData( byteBuffer );
}
byteBuffer.compact();
socketChannel.read(byteBuffer);//
这是默认设置。去掉这个

        buf.clear();
        buf.limit(0);
        while( true ) {
            selector.select();
缓冲区已为空,因为您刚刚分配了它。去掉这个

        buf.clear();
        buf.limit(0);
        while( true ) {
            selector.select();
在clear()之后以及初始分配之后,限制已经为零。去掉这个

        buf.clear();
        buf.limit(0);
        while( true ) {
            selector.select();
这里应该有一个select()调用

            Iterator<SelectionKey> it = selector.selectedKeys().iterator();
            // ...
            if( key == keyData && key.isConnectable() ) {
                    ch.finishConnect();
完全不正确。您完全忽略了
read()
返回-1的情况,这意味着对等方已断开连接。在这种情况下,必须关闭通道

            // without this Thread.sleep, it would not trigger the error
那么?硬币没掉吗?解除睡眠。这完全是毫无意义的。
select()。它不需要你的帮助。这种睡眠简直是浪费时间

            if( rnd.nextInt(20) == 0 ) {
                Thread.sleep(300);
            }
去掉这个

        buf.clear();
        buf.limit(0);
        while( true ) {
            selector.select();

这应该是循环的顶部,而不是底部。

我原来是驱动程序的问题,至少看起来是这样

我使用USB到以太网适配器“D-Link E-DUB100 RevA
由于wireshark显示了正确的数据,我认为消除硬件故障是可能的原因。
但与此同时,我尝试了“D-Link E-DUB100 RevC1”,问题消失了。
因此,我假设D-Link为Rev a提供的驱动程序存在问题。对于Rev C1,它可能使用没有此问题的系统驱动程序


感谢大家花时间阅读我的问题。

虽然Java中可能存在错误,但极不可能。。。考虑到大量其他Java 8程序员(显然)没有遇到这种问题。这很可能是代码中的错误。怎么办?如果你的代码太难简化为MCVE,太大而无法向我们展示,那么你最好的办法就是让同事来帮助你。如果代码都在一个线程上执行,那么就不可能是正常意义上的“竞争条件”。(我不知道这是否有帮助…)从您提到的内容来看,您使用数据的方式可能存在问题。不过这只是一个猜测。由于某些原因,您所提到的并没有解释——当读取数据的java线程在300ms后被调度时,您会背靠背接收到如此多的90字节数据包。如果您假设以90字节的块读取它们,请明确以90字节读取。然后当它们超过90字节时,消耗更多。我不知道确切的API,但可能这应该指向某个方向?可能问题是您阅读的是
buf
,而不是
byteBuffer
?说真的,在不知道缓冲区到底在做什么的情况下,我们应该如何帮助您?例如,
handleData(byteBuffer)
做什么?但是当我在程序中更改太多时,问题就消失了。这是你能得到的最模糊和最不具体的。你知道这是一个最小的例子吗?read()->-1大小写不相关。字节顺序/清除/限制可能是冗余的,但它没有错。这里的重点是Thread.sleep。因为我想触发一个更复杂的程序中出现的问题。我知道这里不需要它。如果选择在最后,第一次迭代将设置一个空的selectedkey。stackoverflow不允许我在代码中粘贴。因此,我通过link.从ByteBuffer.allocate的javadoc发布:“新缓冲区的位置将为零,其限制将是其容量”。这意味着需要限制(0)调用。