如何创建一个Thread安全的InputStream.在多线程操作中,inputStream数据被破坏,所以如何使我的inputStream线程安全.将使用以下代码工作
public class SynchronizedInputStream extends InputStream{ private InputStream in; private SynchronizedInputStream( InputStream in ) { this.in = in; } /* ... method for every InputStream type to use */ public static InputStream createInputStream( InputStream in) { return new SynchronizedInputStream( in); } public static InputStream createPushBackInputStream(InputStream in,int BUFSIZE){ return new SynchronizedInputStream(new PushbackInputStream(in,BUFSIZE)); } /* Wrap all InputStream methods Used */ public int read(){ synchronized (this) { try { return in.read(); } catch (IOException e) { e.printStackTrace(); } } return 0; } @Override public int available() { synchronized( this ) { try { return in.available(); } catch (IOException e) { e.printStackTrace(); } } return 0; } }
在NANOHTTPD文件中
public HTTPSession(TempFileManager tempFileManager, InputStream inputStream, OutputStream outputStream, InetAddress inetAddress) { this.inputStream=(PushbackInputStream) SynchronizedInputStream.createPushBackInputStream(inputStream); /*lines of code..........*/ }
然后我就这样称呼它
String Data = readStream(session.getInputStream());//session is HTTPSession /*.....code....*/ private String readStream(InputStream in) { synchronized (in) { PushbackInputStream inputStream = (PushbackInputStream) in; StringBuffer outputBuffer = null; try { //Reading the InputStream Here } } catch (IOException ioe) { //error msg } return outputBuffer.toString(); } }
Enno Shioji.. 9
你需要考虑它是如何有意义的.想象一下,不止一个人正在阅读一本魔法书,它会在人们第一次看到它时删除这个角色.所以只有一个人可以阅读任何给定的角色.这就是流的方式.
这使得以有用的方式阅读本书变得非常困难.当最天真地完成时,每个人都会得到一些随机的角色子集; 不是很有用的信息.
一个直接的解决方案是让一个人阅读它,然后将其复制到一本书上,当一个人读取它时不会删除字符.这样每个人都可以阅读这本书.在某些情况下,你并不需要每个人都能理解这本书,只要给出一个句子,人们就可以工作.在这种情况下,一个读者可以将每个句子发布到一个队列,每个人每次都要一个句子.
其他方法包括具有缓冲区,其中每个线程存储它们读取的字符,然后每次检查它们是否可以形成单词,并且如果是这样则发出单词用于下游处理.有关示例,请参阅Netty的编解码器包(例如,此).
然而,这些方法通常在流的顶部而不是在流内部实现.你可能有一个在里面做这些的流,但它可能会让人迷惑.
简短的回答是,您向我们展示的类是线程安全的,但使用您的类的代码可能不是线程安全的!
你实现的是以原子方式读取一个字符的操作,并自动测试是否有要读取的内容.这些操作的实现是线程安全的,如果(并且仅当)所有线程使用相同的SynchronizedInputStream
对象来访问给定的InputStream
,并且除了包装器之外没有任何东西InputStream
直接访问.
但是,这很可能是因为这不足以使您的应用程序在更广泛的意义上使用流线程安全.
我希望你所观察到的"腐败"实际上发生的程度更高; 例如,两个同时进行read
读取(比方说)消息调用的线程正在交错,因此消息的某些字节将进入错误的线程.假设这是你的问题,那么这并没有解决它.您的read
方法仅在线程读取单个字节时锁定流.解锁后,没有什么可以阻止不同的线程读取下一个字节.
有几种方法可以解决这个问题.例如"
一个简单的方法,就是要调整你的代码只有一个线程不断从给定读取InputStream
.该线程读取消息,并将它们转换为可以通过队列传递给其他人的对象......例如.
另一种方法是用一个以原子方式读取整个消息的类来替换你的包装类.不要延长InputStream
.而是根据较大规模的操作设计API,并在该粒度级别进行同步.
UPDATE
重新添加您添加的额外代码.
它看起来像只有一个线程(当前请求的线程)不应当从输入流中读取.如果您只使用一个线程,那么多线程或线程安全应该没有问题.(此外,这就是nanoHTTPD代码的工作方式.)
假设存在多个线程,只要所有线程都使用相同的对象,您的synchronized (in) {
块readStream
通常就足以使代码成为线程安全的in
.
问题是你的黑客HttpSession
类正在SynchronizedInputStream
为每个"会话" 创建一个单独的,这就是你的代码同步的东西.因此,如果(某种程度上)两个线程HttpSessions
使用相同的套接字输入流创建对象,它们将在不同的对象上同步,并且不存在互斥.
但这都是猜想.到目前为止,您尚未证明有多个线程尝试使用相同的输入流.
你需要考虑它是如何有意义的.想象一下,不止一个人正在阅读一本魔法书,它会在人们第一次看到它时删除这个角色.所以只有一个人可以阅读任何给定的角色.这就是流的方式.
这使得以有用的方式阅读本书变得非常困难.当最天真地完成时,每个人都会得到一些随机的角色子集; 不是很有用的信息.
一个直接的解决方案是让一个人阅读它,然后将其复制到一本书上,当一个人读取它时不会删除字符.这样每个人都可以阅读这本书.在某些情况下,你并不需要每个人都能理解这本书,只要给出一个句子,人们就可以工作.在这种情况下,一个读者可以将每个句子发布到一个队列,每个人每次都要一个句子.
其他方法包括具有缓冲区,其中每个线程存储它们读取的字符,然后每次检查它们是否可以形成单词,并且如果是这样则发出单词用于下游处理.有关示例,请参阅Netty的编解码器包(例如,此).
然而,这些方法通常在流的顶部而不是在流内部实现.你可能有一个在里面做这些的流,但它可能会让人迷惑.