如何最有效地从多个线程访问共享文件?

问题描述 投票:1回答:1

我正在开发一个小型Web应用程序,其Servlet定期访问共享资源,该资源是服务器端包含一些可变数据行的简单文本文件。在大多数情况下,servelt只是读取文件中的数据,但是某些servelt可能还会更新它,在文件中添加新行,或者删除并替换现有行。尽管文件内容不是很经常更新,但是如果两个或多个Servlet决定同时读写文件,则数据不一致和文件损坏的可能性仍然很小。

首要目标是确保文件读写的安全性。为此,我创建了一个帮助程序FileReaderWriter类,提供了一些用于线程安全文件访问的静态方法。读取和写入方法由ReentrantReadWiteLock协调。规则很简单:只要没有其他线程同时写入文件,多个线程就可以随时从文件中读取。

public class FileReaderWriter {
    private static final ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock();

    public static List<String> read(Path path) {
        List<String> list = new ArrayList<>();
        rwLock.readLock().lock();
        try {
            list = Files.readAllLines(path);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            rwLock.readLock().unlock();
        }
        return list;
    }

    public static void write(Path path, List<String> list) {
        rwLock.writeLock().lock();
        try {
            Files.write(path, list);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            rwLock.writeLock().unlock();
        }
    }
}

然后,每个Servlt都可以使用上述方法读取文件,如下所示:

String dataDir = getServletContext().getInitParameter("data-directory");
Path filePath = Paths.get(dataDir, "test.txt");
ArrayList<String> list  = FileReaderWriter.read(filePath);

类似地,可以使用FileReaderWriter.write(filePath, list)方法进行写入。注意:如果需要替换或删除某些数据(这意味着从文件中获取数据,对其进行处理并将更新后的数据写回到文件中),则此操作的整个代码路径应由rwLock.writeLock()锁定,以确保原子性原因。

现在,当访问共享文件似乎很安全(至少,我希望如此)时,下一步就是要使其更快]]。从可伸缩性的角度来看,应每个用户的请求向Servlet读取文件听起来并不合理。因此,我想到的是在上下文初始化期间仅将文件的内容读入ArrayList(或其他集合)一次,然后将该ArrayList(而不是文件)作为上下文范围的数据持有者属性来共享。然后,可以使用与上述相同的锁定机制由servlet共享上下文范围的属性,并且可以在某些常规基础上将更新后的ArrayList的内容独立存储回文件中。

[另一种解决方案(为了避免锁定)将使用CopyOnWriteArrayList(或java.util.concurrent程序包中的其他集合)来保存共享数据,并指定单线程ExecutorService将其内容转储到文件中需要的时候。我也听说过Java内存映射文件将整个文件映射到内部存储器,但是不确定这种方法是否适合这种特殊情况。

因此,任何人都可以指导我彻底解决最有效的方法(也许是建议其他替代方法),以解决共享文件访问的问题,但前提是写入文件的频率非常低并且其内容是预计不会超过数十行。

我正在开发一个小型Web应用程序,其Servlet定期访问共享资源,该资源是服务器端包含一些可变数据行的简单文本文件。大多数情况下,servlts ...

java multithreading servlets file-io
1个回答
0
投票

您不解释自己的真正问题,仅是您当前的尝试,很难提供一个好的解决方案。

© www.soinside.com 2019 - 2024. All rights reserved.