所有CRUD操作的线程安全列表

时间:2018-11-06 13:25:12

标签: java multithreading

最近我进行了编码练习,必须创建以下三个服务:

  • 创建:创建新交易
  • 获取:获取过去60秒内的所有记录并删除所有较旧的记录
  • 删除:删除所有交易

因此,对于这些服务,我创建了以下用于事务存储的类。但是根据我的代码审阅者的说法,以下代码不是线程安全的。

由于使用多种方法添加和删除过时的交易,在某些情况下可能会丢失有效的交易。

有人可以查看以下代码,并告诉我在线程安全性和性能方面我可以改进的地方吗?

public class TransactionMemory {

    private List<Transaction> transactions = new CopyOnWriteArrayList<>();

    public void newTransaction(Transaction transaction) {

        transactions.add(transaction);
    }

    public List<Transaction> trxsInLast60Seconds() {
        List<Transaction> filteredTransactions = transactions.stream()
                .filter(p -> Instant.parse(p.getTimestamp()).isAfter(DateHelperUtils.getLast60SecondsByNow()))
                .collect(Collectors.toList());
        removeOldTransactions(filteredTransactions);
        return filteredTransactions;
    }

    private void removeOldTransactions(List<Transaction> filteredTransactions){
        transactions.retainAll(filteredTransactions);
    }
    public void deleteTransactions() {
        transactions.clear();
    }
}

1 个答案:

答案 0 :(得分:2)

CopyOnWriteArrayList类确实是线程安全的,但是由于

  

所有可变操作(添加,设置等)均由以下方式实现   制作基础数组的新副本

这是使用ArrayList的解决方案:

public class TransactionMemory {

    private final List<Transaction> transactions = new ArrayList<>();

    public synchronized void newTransaction(Transaction transaction) {
        transactions.add(transaction);
    }

    public synchronized List<Transaction> trxsInLast60Seconds() {
        List<Transaction> filteredTransactions = transactions.stream()
                .filter(p -> Instant.parse(p.getTimestamp()).isAfter(DateHelperUtils.getLast60SecondsByNow()))
                .collect(Collectors.toList());
        removeOldTransactions(filteredTransactions);
        return filteredTransactions;
    }

    private void removeOldTransactions(List<Transaction> filteredTransactions) {
        transactions.retainAll(filteredTransactions);
    }

    public synchronized void deleteTransactions() {
        transactions.clear();
    }
}

由于所有可变操作都已同步,因此它是线程安全的。