gpt4 book ai didi

java - 高效等待资源

转载 作者:行者123 更新时间:2023-11-30 09:04:48 24 4
gpt4 key购买 nike

我想知道解决这个问题的最有效方法是什么。

我有一个多线程数据库实现(例如 LevelDB),我希望它能处理同步,因为它可以做得更好。但是,我想异步初始化数据库,而不阻塞任何线程,除非它们以某种方式想在数据库打开之前使用它。

类似的东西:

public class Storage {
Database db;

public Storage() {
open();
}

private void open() {
new Thread(new Runnable() {
public void run() {
// attempt to open db here, i.e. change the value of Storage.db from null
// into Object
}
}).run();
}

public void accessMethod() {
// this method should only use a non-null Storage.db value, it should block
// until the thread above does not set the value of db to be an Object
}

public void nonAccessMethod() {
// this method is not concerned with the value inside Storage.db and should not
// block while the thread above is running
// example: memory cached operations on the db which will be executed after
// the thread above finishes and "unlocks" Storage.db
}
}

我想出了这个解决方案,但效率不高:

public class Storage {
ReentrantLock lock;

Database db;

public Storage() {
lock = new ReentrantLock();

open();
}

private void open() {
lock.lock(); // to be released in thread below

new Thread(new Runnable() {
public void run() {
// heavy work here while populating Storage.db

lock.unlock();
}
}).run();
}

// returns true if the database is not yet open and that we need to release
// the lock once our code segment completes
private boolean blockIfNotOpen() {
if (lock.tryLock()) {
lock.unlock(); // << this code segment sucks

return false;
} else {
lock.lock();

return true;
}
}

public void accessMethod() {
boolean wasNotOpen = blockIfNotOpen();

// "blocking" code here

if (wasNotOpen) {
lock.unlock();
}
}

public void nonAccessMethod() {
// not concerned with Storage.db and therefore not trying to lock
}
}

我不喜欢这个解决方案,因为在填充 Storage.db 很久之后,它仍然在 Storage 的实现中同步对数据库的访问,而实际上在 DB 中有一个底层系统可以更好地处理并发(例如:DB 暴露工作线程等)。

在 Storage 对象上同步不是解决方案,因为它会一直同步,而不是仅在 Storage.db 为 null 时同步。

注意:如果您担心锁,我保证在 Storage 的构造函数完成之前不会有并发调用。 :) 所以,所有并发都发生在构造函数之后。

最佳答案

我认为解决方案是在构造函数中使用 ReadWriteLock - writeLock().lock()writeLock().unlock()数据库初始化后,readLock() 被数据库消费者使用。

另一种选择,使用 Future:

public class Storage {
private final Future<Database> dbFuture = Executors.newSingleThreadExecutor().submit(
new Callable<Database>()
{
public Database call()
{
return new Database(...);//Long running DB initialisation
}
}
);

public void accessMethod()
{
Database db = dbFuture.get();// will wait while the call() is not completed yet.
}
}

关于java - 高效等待资源,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25082815/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com