getResourceAsStream线程安全吗?

时间:2014-09-19 14:12:50

标签: java multithreading

网络服务器上的代码:

public byte[] loadData() {
    byte[] data = null;
    try(final InputStream resourceStream = getClass().getResourceAsStream("data.bin")) { 
        data = ByteStreams.toByteArray(resourceStream); //ByteStreams is from Guava library
    } catch (IOException e) {
        e.printStackTrace();
    }
    return data;
}

多个线程在资源上打开流并读取其内容是否存在问题?在这种情况下,资源是jar中包含的数据文件。

在Windows上同时读取资源不是问题。但是效率不高所以我选择使用WeakReference和双重检查锁定只加载一次数据。

3 个答案:

答案 0 :(得分:5)

可能可能在线程之间共享的唯一状态是InputStream返回的getResourceAsStream(String)。我们来检查它是否是同一个对象。

这是一个非常简单的测试,您可以自己尝试一下:

InputStream first = getClass().getResourceAsStream("data.bin")
InputStream second = getClass().getResourceAsStream("data.bin")
System.out.println(first == second);

这将(通常)返回false。由于它们不是同一个对象,因此没有线程安全问题。


我说通常是,因为getResourceAsStream取决于加载ClassLoader返回的Class实例的基础getClass()。因此,除非您正在编写和使用自己的(或第三方)ClassLoader个对象,否则您将没事。

答案 1 :(得分:1)

通常,您可以通过getClass().getClassLoader().getResourceAsStream()访问上述文件。读取文件总是安全的,即不需要同步。

答案 2 :(得分:-5)

No,同时访问同一文件的多个线程在某个时刻抛出异常,因为没有共享读访问,每次从任何线程成功打开文件时,您的文件都会被锁定,在文件再次关闭之前,所有其他线程都将失败。

您可以使用synchronized关键字避免异常,这将使您能够在不遇到任何问题的情况下启动任意数量的线程 - 请注意:由于线程将被强制执行顺序中的函数方式,你的阅读表现将大幅下降。

另一种可能性是FileChannel,这些类似乎是设计线程安全的

编辑:显然这个问题几年前已经解决了 - 但只有在java中使用“新文件系统API”时才会看到更多信息的评论