我有一个Spring Boot Web应用程序。其中一个服务有一个生成CSV文件并将其保存到磁盘的方法。然后,此方法将文件位置传递给另一个方法,该方法通过电子邮件发送CSV文件,然后将其从磁盘中删除。为了避免并发问题,我决定将线程Id添加到文件名中,如下所示:
@Service
public class ReportService {
@Autowired
private ReportRepository serviceRepository;
public List<item> generateReport(Timestamp minTime, Timestamp maxTime) {
// some code to retrieve items list.
String reportTitle = "report-" + Long.toString(Thread.currentThread().getId()) + ".csv";
CsvFileWriter report = new CsvFileWriter(reportTitle);
File file = report.writeCsvFile(data);
File[] attachments = { file };
sendReportViaEmail("Please find monthly report attached.", attachments);
return items;
}
private void sendReportViaEmail(String body, File[] attachments) {
// This method sends CSV via email and then delete the 'attachments' from disk.
}
}
到目前为止它似乎正在发挥作用。我想知道的是,这是否是在我的情况下避免竞争条件的好方法。更具体地说,
sendReportViaEmail()
是否始终在与调用generateReport()
的线程相同的线程中调用? 答案 0 :(得分:1)
您所做的工作将起作用,因为Thread
的ID在JVM中保证是唯一的。
根据评论中的建议使用currentTomeMilis
是不一个好主意,因为这不保证是唯一的(两个线程可能同时调用它)并得到完全相同的值。)
如果您想使用内置工具执行此操作,请查看File.createTempFile()
。但请注意,实现(至少在Oracle 1.7中)取决于随机数,并且当两个线程同时访问它时和获得相同的随机数(非常不可能但可能),该方法将抛出IOException
。
另一个方法将在同一个线程中调用,如果你调用它......好吧,从线程。