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

Avoiding race conditions using thread Id in Java (Spring)?

我有一个 Spring 引导网络应用程序。其中一项服务具有生成 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. 是否总是在与调用 generateReport() 的线程相同的线程中调用 sendReportViaEmail()

您所做的会奏效,因为 Thread 的 ID 保证在 JVM 中是唯一的。

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

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


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