我试图在过去几天找到以下答案,但无法找到全面的答案
问题陈述
我有一个自定义JSP标记类,它处理Web表单提交,捕获数据并将其写入文件系统中的同一文件。 作为所有Web应用程序,这可以同时触发,我担心多个线程将处理每个提交(我们都知道Servlet是如何工作的。)
CODE
synchronized (this){
final String reportFileName = "testReport.csv";
File reportDir = new File( rootCsDirectory, "reports" );
if(!reportDir.isDirectory())reportDir.mkdir();
File reportFile = new File (reportDir, reportFileName);
logReport(reportFile,reportContent.toString());
}
ISSUE: - 一个线程可以打开一个File对象进行写入,同时另一个线程可能会尝试访问并失败并抛出异常 所以我想同步(在对象上)应该解决问题,但是读一些 jsp引擎会有jsp标签对象池的地方,所以我担心 synchronized(this)不会工作,应该更改为 synchronized(this.getClass()) 仅供参考:上面的代码放在JSP自定义标记类中。
编辑:
问题1:应该通过 synchronized(this)或 synchronized(this.getClass()) 来同步代码块p>
问题2:如果在群集环境中部署Web应用程序,将如何处理相同的方案?
答案 0 :(得分:1)
我会在更精细的级别进行同步,并选择一个与文件创建更紧密相关的对象。
e.g。将上面的内容抽象为一个FileManager
类,并让一个单个实例在锁定对象上同步(在FileManager
内部保持 - 它可能会自行锁定,也许)。
通过这种方式,您可以更精细地控制同步,并且可以更好地控制要锁定的对象。它们不受servlet / web容器的控制。
答案 1 :(得分:0)
如何将它放在同步方法中,以便您可以高兴地忽略JSP的管理细节?
答案 2 :(得分:0)
我会查看java.util.concurrent包中的内容。
您可以使用cuncurrent队列来推送更新,并在另一端使用在应用程序启动时生成的线程,该线程会对文件系统进行写入。
这将很好地有效地序列化对该文件的访问。