- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
设置
我有一个多线程 Java 应用程序,每秒将接收 200-300 个请求,以对请求中收到的输入执行任务“A”(大约需要 30 毫秒)。
应用程序有一个缓存(最大大小 = 1MB),每个线程都会读取该缓存以在接收到的输入上执行任务“A”:
public class DataProvider() {
private HashMap<KeyObject, ValueObject> cache;
private Database database;
// Scheduled to run in interval of 15 seconds by a background thread
public synchronized void updateData() {
this.cache = database.getData();
}
public HashMap<KeyObject, ValueObject> getCache() {
return this.cache;
}
}
KeyObject 和 ValueObject 是 POJO。 ValueObject 包含另一个 POJO 的 List。
对于收到的每个请求,任务都按以下方式完成:
public class TaskExecutor() {
private DataProvider dataProvider;
public boolean doTask(final InputObject input) {
final HashMap<KeyObject, ValueObject> data = dataProvider.getCache(); // shallow copy I think
// Do Task 'A' using data
}
}
问题
其中一个线程开始使用缓存中的数据“d1”在时间戳“t”处执行任务“A”。在时间“t + t1”,缓存数据更新为“d2”。线程现在开始使用数据“d2”来完成任务的其余部分。任务在“t+t1+t2”完成。使用不同的数据完成了一半的任务。这将导致任务结果无效。
当前方法
每个线程都会创建缓存的深层复制,然后使用深层复制来执行任务,使用以下方法之一(性能最佳)来执行深层复制:
How do you make a deep copy of an object in Java?
Deep clone utility recommendation
限制
使用深层复制进行克隆将创建数千个对象,这可能会导致 JVM 崩溃。
所有克隆方法在性能方面看起来都不太好。
最佳答案
对于您的用例,从 database.getData();
返回新的缓存是更好的选择。因为如果您选择这种方式,您只需在 15 秒内创建一次新的缓存对象。如果您选择在每个任务中克隆缓存,则必须在 15 秒内创建 4501 个缓存对象。显然返回新的缓存对象是正确的选择。
如果您提供的代码与您的项目中的代码相同,我相信 database.getData();
方法会更改单个缓存对象的内容,而不是返回一个新的。如果您从此方法返回一个新的缓存对象,您的问题将得到解决。
关于java - 在多线程 Java 应用程序中创建缓存的深拷贝,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54723150/
拿这个: var lists:{ item1:{} ,item2:{} ,item3:{} ,item4:{} } 由于它基本上是空的,我想要一个函数(可能但不一定是 _lodash
我想更改 ng bootstrap 分页组件的样式并在 Angular 6 应用程序中使用 /deep/ 链接。以下代码工作正常,但控制台显示警告,指出该代码已被弃用。 那么,我应该如何更改它以消除警
使用 webcomponents,您可以使用 /deep/ 定位 shadowdom 的内部元素,在我尝试使用事件委托(delegate)之前它工作正常。 一个常规的点击功能将起作用: $('html
在 Swift 中,我试图实现一个单词 Trie,使用文字表示作为一系列嵌套的 NSObject。这是 Trie。 let GEENITRIE:NSObject = [ "i":[
运行 npm update 更新 package.json 中列出的项目;但是,这些项目的依赖关系仍然过时。 明显的解决方法是再次运行 npm update。有时我需要运行它 3 次以上才能使 npm
我创建了 2 级嵌套 linq 查询: var data = (from p in Departments join e in Employees on p.Id equals
首先是代码 #include typedef wchar_t* BSTR; wchar_t hello[] = L"Hello"; class _bstr_t { public: opera
我要编写一个 lisp 程序来生成十六进制数的实际值。我已经编写了一个函数,但似乎出现了 stackoverflow(深度)错误。我想知道是否有人可以指出我的错误或指导我朝着正确的方向前进。 如果没有
我想将每种类型都转换为boolean 或object type CastDeep = { [P in keyof T]: K extends K[] ? K[] : T[P] ex
我刚刚发现自己在写这个: fn init_timestamps(dir: &PathBuf, file_timestamps: &'static HashMap) { match fs::re
我有一个现有的 pybind11::array_t,需要进行复制构造。 pybind11 中是否有一个函数允许我对 array_t 进行深度复制? 我知道我可以创建一个新的 array_t,适当调整大
引用http://www.devx.com/tips/Tip/13291 ,它说我可以使用 memcpy 来复制由 sizeof() 确定的大小,但是,数组不是指向指针吗? 除了遍历数组,如何使用 m
我有多个成员(member),每个成员(member)都有一条记录,其中包含几个备注字段: Member ID Entry A Entry B 1 [memo t
$watchCollection 是否能够忽略对以 $ 开头的属性的更改?使用深度 $watch 时已经存在此行为,因为它依赖于 angular.equals 进行比较。 理想情况下,$watchCo
我有一个带有复杂键的 map - 例如,二维数组: m := make(map[[2][3]int]int) 当我在映射中插入一个新键时,Go 是否会对该键进行深度复制? a := [2][3]int
我需要查询如下所述的三个表。我了解简单的 JOIN,但是这个有点超出我的水平。 courses 有两列 id (PK) 和 courseTitle(示例 id 1,courseTitle 物理) cl
我有一个对象,它是 Realm 的 Object 子类,并且符合 Codable 以便在与 API 对话时与 JSON 相互转换。 如何利用 Codable 协议(protocol)进行深度复制(包括
我是一名优秀的程序员,十分优秀!