我有一个类,我们称之为Foo foo,它包含对多个线程有用的数据。这些线程可以调用读写操作(例如 foo->emplace(something((,我由 Foo 内部的互斥锁保护这些操作,并在操作中添加了互斥锁。这是我在实施方面不确定的地方。我必须向foo添加另一条共享信息,我必须调用foo->emplace2(somethingElse(,这将在std::set中存储一些东西,但这应该只存储一分钟。
正确的方法是什么?每当调用 emplace2 并在该线程 emplace 内部休眠 60 秒,然后擦除时,我是否都会从 foo 内部创建一个新线程?我觉得有一种比每次调用 emplace2 时创建大量线程更好的方法。
不是寻找代码,只是一般的实现建议。
您有几个选择:
每个请求一个线程
又名您的解决方案
优势:
- 易于实施
- 精确的移除时间
弊:
- 创建了很多线程。但话又说回来,所有的线程都睡了一辈子,所以这可能不是一个值得解决的问题。
一个队列和一个线程定期检查过期的请求
创建一个队列,用于存储所有请求及其过期时间。有一个线程定期唤醒并删除所有过期的线程
优势:
- 易于实施
- 只有一个线程
弊:
- 必须做出妥协:
- 增加唤醒和检查频率:这增加了删除请求的精确时间,但也增加了无用唤醒的次数
- 降低唤醒和检查频率:这降低了删除请求的精确时间,但减少了无用唤醒的次数
一个线程具有精确的唤醒
创建一个包含所有请求及其过期时间的队列。有一个线程仅在下一个请求过期时唤醒。
添加请求时:发出信号并唤醒线程,重新计算下一个过期时间并休眠,直到该时间。
唤醒时:删除即将过期的请求,计算到下一个过期的时间,并在该请求之前休眠。
优势:
- 最佳性能
- 精确的移除时间
缺点:
- 难以实施
什么是最好的方法...
与往常一样,答案是:"视情况而定"。我给了你一些选项,并对每个选项进行了简要分析。由您决定实施哪个,该决定是在性能要求与实施和维护成本之间取得平衡。