3 回答

TA贡献1878条经验 获得超4个赞
您可以使用ReentrantLock。锁一次只允许一个线程,它的tryLock()方法将根据是否获得锁立即返回 true 或 false。
ReentrantLock lock = new ReentrantLock();
methodA() {
...
if (lock.tryLock()) {
try {
doSomething();
} finally {
lock.unlock();
}
}
...
}
如果您想doSomething()在另一个线程中执行,并且不想阻塞任何调用线程,您可以使用与您最初想到的类似的东西。
AtomicBoolean flag = new AtomicBoolean();
methodA() {
...
if (flag.compareAndSet(false, true)) {
// execute in another thread / executor
new Thread(() -> {
try {
doSomething();
} finally {
// unlock within the executing thread
// calling thread can continue immediately
flag.set(false);
}
}).start();
}
...
}

TA贡献1773条经验 获得超3个赞
我认为您可以使用 ReentrantLock 及其tryLock
方法。从文档ReentrantLock::tryLock
仅当调用时锁未被另一个线程持有时才获取锁。
如果当前线程已经持有此锁,则持有计数递增 1,并且该方法返回 true。
如果锁被另一个线程持有,则此方法将立即返回值 false。
所以你可以在你的服务中创建这样的锁作为一个字段,这样调用你的线程methodA
将共享它然后:
public class MyService {
private ReentrantLock reentrantLock = new ReentrantLock();
public void methodA() {
if(reentrantLock.tryLock()) {
doSomething();
reentrantLock.unlock();
}
}
}
编辑:这里的锁将通过调用 Thread 来持有,这个线程将等待提交的任务完成然后解锁锁:
public class MyService {
private ReentrantLock reentrantLock = new ReentrantLock();
private ExecutorService pool = Executors.newCachedThreadPool();
public void methodA() {
if(reentrantLock.tryLock()) {
Future<?> submit = pool.submit(() -> doSomething()); // you can submit your invalidateCacheRunnableTask runnable here.
try {
submit.get();
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
} finally {
reentrantLock.unlock();
}
}
}
}
还要记住,我在这个例子中使用了 threadPool,所以这个池需要适当地关闭

TA贡献1777条经验 获得超10个赞
我建议您使用阻塞队列,而不是使用某种显式锁。我看到的优点是,如果/当需要时,您不需要重复生成线程。您只需要生成一个线程一次,该线程将只处理所有doSomething。
设想:
调用methodA时,它会将专用线程的必要信息放入 BlockingQueue 并继续运行。专用线程将从BlockingQueue 中轮询信息(在空队列上阻塞)。当队列中收到一些信息时,它会运行您的doSomething方法。
BlockingQueue<Info> queue;
methodA() {
//...
queue.add(info);
// non-blocking, keeps going
}
void dedicatedThread(){
for(;;) {
//Blocks until some work is put in the queue
Info info = queue.poll();
doSomething(info);
}
}
注意:我假设类型Info包含方法doSomething的必要信息。但是,如果您不需要共享任何信息,我建议您改用信号量。在这种情况下,方法 A 会将票放入信号量中,专用线程将尝试绘制票,阻塞直到收到一些票。
添加回答
举报