java中线程安全的InputStream

java中线程安全的InputStream,java,multithreading,inputstream,Java,Multithreading,Inputstream,如何创建线程安全的InputStream。在多线程操作期间,InputStream数据会损坏,因此如何使我的InputStream线程安全。以下代码有效吗 public class SynchronizedInputStream extends InputStream{ private InputStream in; private SynchronizedInputStream( InputStream in ) { this.in = in; }

如何创建线程安全的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();

        } 
    }

你需要想一想这有什么意义。想象一下,不止一个人在读一本魔法书,当有人第一次看到它时,它会将角色擦除。因此,只有一个人可以阅读任何给定的字符。溪流就是这样的

这使得以一种有用的方式阅读这本书变得非常困难。最天真的时候,每个人只会得到一些随机的字符子集;不是很有用的信息

一个直截了当的解决方案是让一个人读它,然后把它复制到一本书上,当一个人读它时,它不会擦除字符。这样每个人都可以读这本书。在某些情况下,你不需要每个人都理解这本书,人们只要给他们一句话就可以工作。在这种情况下,一个读者可以将每个句子发布到一个队列中,每个人一次从队列中获取一个句子

其他方法包括使用缓冲区,每个线程在其中存储它们读取的字符,然后每次检查它们是否可以形成一个字,如果可以,则发出该字以供下游处理。例如,请参阅Netty的编解码器包(例如)


然而,这些方法通常在流的顶部实现,而不是在流内部实现。您很可能有一个在内部执行这些操作的流,但它可能会让人困惑。

简单的回答是,您向我们展示的类是线程安全的,但是使用您的类的代码可能不会是线程安全的

您所实现的操作是以原子方式读取一个字符,并以原子方式测试是否有要读取的内容。如果(且仅当)所有线程都使用相同的
SynchronizedInputStream
对象访问给定的
InputStream
,并且除了包装器之外,没有任何内容可以直接访问
InputStream
,则这些操作的实现是线程安全的

然而,这很可能不足以使应用程序在更大意义上使用streams线程安全

我预计你所观察到的“腐败”实际上正在更高层次上发生;e、 g.两个线程同时进行一系列的
read
调用以读取(比如)消息,这两个线程交错进行,因此消息的某些字节将进入错误的线程。假设这是你的问题,那么这并不能解决它。
read
方法仅在线程读取单个字节时锁定流。解锁后,没有任何东西可以阻止另一个线程读取下一个字节

有几种方法可以解决这个问题。例如“

  • 一种简单的方法是重新构造代码,只有一个线程从给定的
    InputStream
    读取消息。该线程读取消息,并将其转换为可以通过队列传递给其他人的对象…例如

  • 另一种方法是将您的包装器类替换为以原子方式读取整个消息的包装器类。不要扩展
    InputStream
    。而是根据更大规模的操作设计您的API,并在该粒度级别进行同步

更新

是您添加的额外代码

看起来只有一个线程(当前请求线程)应该从输入流中读取。如果您只使用一个线程,那么多线程或线程安全性应该没有问题。(此外,这也是nanoHTTPD代码设计的工作方式。)

假设有多个线程,如果所有线程都在对象中使用相同的
,那么
readStream
中的
synchronized(in){
块通常足以使代码线程安全

问题是你被黑客攻击的
HttpSession
类正在为每个“session”创建一个单独的
SynchronizedInputStream
,这就是你的代码同步的原因。所以如果(不知何故)两个线程使用相同的套接字输入流创建了
HttpSessions
对象,它们将在不同的对象上同步,并且不会相互排斥


但这都是猜测。到目前为止,您还没有证明有多个线程试图使用同一个输入流。

可能。但您还必须确保没有其他人直接访问
中的底层
。为什么要将一个inputstream多线程化?您试图实现什么,您的问题在哪里m?对我来说,尝试围绕输入流进行同步并没有什么意义……保持它是单线程的,但切换到生产者/消费者模式可能更有意义。要么就是这样,要么就是制作一个线程安全适配器,将输入流变为阻塞队列。无论哪种方式,都要意识到能够对read()进行并发调用不会神奇地使您的代码线程安全;线程仍然必须相互协调读取,因此选择不同的方法。如果您尝试在多个线程中读取流,则会出现设计问题。如果您希望多线程,我会让一个且只有一个线程读取流,并让该线程将工作传递到线程池-读取数据的线程处理。您永远不应该需要多个线程来读取流,因为这将以尽可能快的速度读取流,而添加线程只会增加复杂性和混乱。