Java线程不会在I / O操作上暂停 [英] Java Thread won't pause on I/O operation

查看:174
本文介绍了Java线程不会在I / O操作上暂停的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的印象是,在Java中,Thread会暂停并让其他线程有机会在阻塞I / O操作(如Socket.read()或DataGramsocket.receive())期间做一些工作。出于某种原因,在我的多线程网络应用程序中,对receive()的调用导致我所有其他线程都饿死(调用receive()的线程正在成为一个大老板,永远不会放弃控制,从而永远阻止!)

I was under the impression that in Java, a Thread will pause and give other threads a chance to do some work during blocking I/O operations ( like Socket.read() or DataGramsocket.receive() ). For some reason in my multi threaded network application, a call to receive() is causing all my other threads to starve ( the thread that called receive() is becoming a big boss and never giving up control, thus blocking forever! )

为什么会发生这种情况?我曾经拥有相同的应用程序,但它不是UDP而是基于TCP。 Socket.read()总是暂停线程并允许其他人工作一段时间,如果它被阻塞了太久。

Why would this happen? I used to have the same exact application, but instead of UDP it was TCP based. Socket.read() always paused the Thread and allowed others to work for a bit if it blocked for too long.

- 额外信息 -
我的自定义线程的TCP版本是这段代码:
http://www.dwgold.com/code/proxy/proxyThread.java.txt

-- extra info -- The TCP version of my custom thread was this code: http://www.dwgold.com/code/proxy/proxyThread.java.txt

我的新代码(UDP版本)几乎相同,但修改了一些使用UDP方法和样式。然后我创建了其中两个线程,并在两个线程上调用start。第一个线程总是阻塞,永远不会让另一个在UDP版本中工作。

My new code ( UDP version ) is pretty much the same, but modified a bit to use UDP methods and style. I then created two of these threads and call start on both. The first thread always blocks and never lets the other do work in the UDP version.

推荐答案

看来你正在使用一个InputStream,而且根据 InputStream.read()的JDK文档/ a>,读取的块与您描述的完全相同 - 直到收到数据,到达文件结尾或抛出异常。

It seems that you're using an InputStream, and according to the JDK docs for InputStream.read(), the read blocks exactly as you've described -- until the data is received, an end-of-file is reached, or an exception is thrown.

所以对我来说,问题是:为什么代码的TCP版本允许块被中断?这似乎没有任何意义。也许你的TCP代码将读取分解为离散的,足够短的突发,线程有机会在单独的read()调用之间跳转?

So for me, the question is: why does the TCP version of your code allow the block to get interrupted? That doesn't seem to make any sense. Perhaps your TCP code breaks the reads up into discrete, short-enough bursts that the thread has a chance to jump in between separate calls to read()?

进一步观察,我看到不同之处在于,代码的TCP版本通过Socket提供的InputStream接收数据,而代码的UDP版本直接从DatagramSocket自己的receive()方法接收数据。所以我认为这只是两者提供的功能(InputStream.read和DatagramSocket.receive)之间的根本区别。您是否考虑过使用 DatagramPacket .setSoTimeout 在套接字的接收块上设置超时,然后在调用receive()时超时的情况下捕获SocketTimeoutException?您应该能够实现这一目标以实现您想要的目标。

Looking further, I see that the difference is that the TCP version of your code receives data via the InputStream that's provided by Socket, whereas the UDP version of your code receives data directly from the DatagramSocket's own receive() method. So I'd posit that this is just a fundamental difference between the functionality offered by the two (InputStream.read and DatagramSocket.receive). Have you thought about using DatagramPacket.setSoTimeout to set a timeout on the socket's receive block, and then catching the SocketTimeoutException when it's thrown by the call to receive() that times out? You should be able to implement this to achieve what you want.

更新:进一步观察,看来 DatagramSocket.receive方法已同步。因此,解释您所看到的行为的方法是,您正在启动两个尝试使用相同DatagramSocket实例的线程 - 如果两个线程试图在同一个DatagramSocket实例上执行receive(),则会阻止实例直到完成,另一个将被阻止。 (这里有 Sun论坛上的帖子,以及。)这可能是正在发生的事情 - 你为两个线程重用相同的DatagramSocket?

UPDATE: looking further still, it appears that the DatagramSocket.receive method is synchronized. So the way to explain the behavior you're seeing is that you're starting two threads that are attempting to use the same DatagramSocket instance -- if two threads are attempting to execute receive() on the same DatagramSocket instance, one will block the instance until it's done, and the other will be blocked. (There's a post on the Sun forums that describes this, as well.) Might this be what's happening -- you're reusing the same DatagramSocket for both threads?

这篇关于Java线程不会在I / O操作上暂停的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆