如何让调用阻塞synchronized方法的线程直接执行后续代码?
实现非阻塞式的processList方法
你的核心需求是让线程调用processList()时,不用等着锁释放,拿不到锁就直接去做别的事——用Java的ReentrantLock就能搞定,替代原来的synchronized方法就行。
具体实现步骤
下面是修改后的ListHolder代码:
import java.util.ArrayList; import java.util.concurrent.locks.ReentrantLock; public class ListHolder { private final ArrayList<Object> list = new ArrayList<>(); // 声明显式锁,替代synchronized方法的隐式锁 private final ReentrantLock processLock = new ReentrantLock(); // 原有的addObject方法保持不变,维持原有线程安全逻辑 public void addObject(Object obj) { synchronized (list) { list.add(obj); } } // 修改为非阻塞的processList方法 public void processList() { // 尝试获取锁,成功返回true,失败直接返回false,不会阻塞线程 if (processLock.tryLock()) { try { // 操作list时仍需与addObject保持同步,避免并发修改异常 synchronized (list) { if (!list.isEmpty()) { // 这里编写你的列表处理逻辑,比如遍历元素、执行业务操作 for (Object obj : list) { // 处理对象的具体代码 } list.clear(); } } } finally { // 无论是否出现异常,必须释放锁,防止死锁 processLock.unlock(); } } // 拿不到锁时直接执行后续代码,线程可去构造新对象,无需等待 } }
关键细节说明
tryLock()是核心:它不会像synchronized那样让线程挂起等待,而是立刻判断能否获取锁,拿不到就直接走后续逻辑,完全匹配你的效率需求。- 操作list的同步块不能省略:因为
addObject()是以list作为锁对象的,处理list时必须使用同一锁,否则会出现并发修改的问题。 - 锁必须在finally块释放:万一处理逻辑抛出异常,finally块能保证锁被释放,避免其他线程永远无法获取锁的情况。
如果你的场景需要短暂等待后再放弃(比如等待100毫秒),可以使用带超时参数的tryLock(100, TimeUnit.MILLISECONDS),但根据你的需求,直接使用无参的tryLock()就足够了。
内容的提问来源于stack exchange,提问作者Andikan Otung
相关产品推荐
相关产品推荐

