在Java(Spring)中使用线程ID避免竞争条件?

时间:2018-02-16 06:24:33

标签: java multithreading concurrency race-condition

我有一个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.
    }

}

到目前为止它似乎正在发挥作用。我想知道的是,这是否是在我的情况下避免竞争条件的好方法。更具体地说,

  1. 如果使用此服务对api资源有并发请求,是否每个请求都由具有唯一线程ID的单独线程处理?
  2. sendReportViaEmail()是否始终在与调用generateReport()的线程相同的线程中调用?

1 个答案:

答案 0 :(得分:1)

您所做的工作将起作用,因为Thread的ID在JVM中保证是唯一的。

根据评论中的建议使用currentTomeMilis一个好主意,因为这不保证是唯一的(两个线程可能同时调用它)并得到完全相同的值。)

如果您想使用内置工具执行此操作,请查看File.createTempFile()。但请注意,实现(至少在Oracle 1.7中)取决于随机数,并且当两个线程同时访问它时获得相同的随机数(非常不可能但可能),该方法将抛出IOException

另一个方法将在同一个线程中调用,如果你调用它......好吧,从线程。