3 回答

TA貢獻(xiàn)1878條經(jīng)驗(yàn) 獲得超4個(gè)贊
您可以使用ReentrantLock。鎖一次只允許一個(gè)線程,它的tryLock()方法將根據(jù)是否獲得鎖立即返回 true 或 false。
ReentrantLock lock = new ReentrantLock();
methodA() {
...
if (lock.tryLock()) {
try {
doSomething();
} finally {
lock.unlock();
}
}
...
}
如果您想doSomething()在另一個(gè)線程中執(zhí)行,并且不想阻塞任何調(diào)用線程,您可以使用與您最初想到的類似的東西。
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貢獻(xiàn)1773條經(jīng)驗(yàn) 獲得超3個(gè)贊
我認(rèn)為您可以使用 ReentrantLock 及其tryLock
方法。從文檔ReentrantLock::tryLock
僅當(dāng)調(diào)用時(shí)鎖未被另一個(gè)線程持有時(shí)才獲取鎖。
如果當(dāng)前線程已經(jīng)持有此鎖,則持有計(jì)數(shù)遞增 1,并且該方法返回 true。
如果鎖被另一個(gè)線程持有,則此方法將立即返回值 false。
所以你可以在你的服務(wù)中創(chuàng)建這樣的鎖作為一個(gè)字段,這樣調(diào)用你的線程methodA
將共享它然后:
public class MyService {
private ReentrantLock reentrantLock = new ReentrantLock();
public void methodA() {
if(reentrantLock.tryLock()) {
doSomething();
reentrantLock.unlock();
}
}
}
編輯:這里的鎖將通過調(diào)用 Thread 來持有,這個(gè)線程將等待提交的任務(wù)完成然后解鎖鎖:
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();
}
}
}
}
還要記住,我在這個(gè)例子中使用了 threadPool,所以這個(gè)池需要適當(dāng)?shù)仃P(guān)閉

TA貢獻(xiàn)1777條經(jīng)驗(yàn) 獲得超10個(gè)贊
我建議您使用阻塞隊(duì)列,而不是使用某種顯式鎖。我看到的優(yōu)點(diǎn)是,如果/當(dāng)需要時(shí),您不需要重復(fù)生成線程。您只需要生成一個(gè)線程一次,該線程將只處理所有doSomething。
設(shè)想:
調(diào)用methodA時(shí),它會將專用線程的必要信息放入 BlockingQueue 并繼續(xù)運(yùn)行。專用線程將從BlockingQueue 中輪詢信息(在空隊(duì)列上阻塞)。當(dāng)隊(duì)列中收到一些信息時(shí),它會運(yùn)行您的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);
}
}
注意:我假設(shè)類型Info包含方法doSomething的必要信息。但是,如果您不需要共享任何信息,我建議您改用信號量。在這種情況下,方法 A 會將票放入信號量中,專用線程將嘗試?yán)L制票,阻塞直到收到一些票。
添加回答
舉報(bào)