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 會將票放入信號量中,專用線程將嘗試繪制票,阻塞直到收到一些票。
添加回答
舉報