Java中如何实现跨线程方法调用及目标线程空闲时执行逻辑
用Java实现跨线程调用方法并等待目标线程空闲
这问题我熟!要实现你想要的效果——让threadA拿到结果后,把doSomethingElse(i)交给threadB执行,还得等threadB空闲了再处理,同时保留原有的逻辑结构,其实核心就是给threadB搭一个串行任务队列,让它按顺序处理提交过来的任务。下面给你两种实用的实现方式:
方式一:用单线程ExecutorService(最简洁推荐)
Java的ExecutorService里的单线程池完美适配这个场景——它内部就是一个固定的线程(相当于你的threadB),所有提交的任务都会按顺序排队执行,前面的任务没完成,后面的就自动等着,完全不用自己写排队逻辑。
代码实现
首先定义你的threadB(用单线程池代替):
// 单线程ExecutorService,这就是专门处理doSomethingElse的threadB ExecutorService threadBExecutor = Executors.newSingleThreadExecutor();
然后修改threadA的逻辑,把执行doSomethingElse的任务提交给线程池:
Thread threadA = new Thread(() -> { int i = doSomething(); // 把doSomethingElse包装成任务提交给threadB,自动排队等待空闲 threadBExecutor.submit(() -> doSomethingElse(i)); });
进阶:如果需要等待doSomethingElse执行完再继续threadA
要是你希望threadA等doSomethingElse执行完再往下走,可以用Future来阻塞等待:
Thread threadA = new Thread(() -> { int i = doSomething(); // 提交任务并获取Future对象 Future<?> taskFuture = threadBExecutor.submit(() -> doSomethingElse(i)); try { taskFuture.get(); // 阻塞等待任务执行完成 } catch (InterruptedException | ExecutionException e) { // 按需处理异常 e.printStackTrace(); } });
方式二:手动用BlockingQueue实现任务队列
如果你想更灵活地控制线程行为(比如自定义中断逻辑、限制队列大小),可以手动用阻塞队列来实现任务传递。阻塞队列的特性就是:当队列空的时候,threadB会阻塞等待任务;threadA提交任务时,队列满了才会阻塞(这里用无界队列的话就不会阻塞threadA)。
代码实现
先初始化任务队列和threadB:
// 用LinkedBlockingQueue作为任务队列,默认是无界的 BlockingQueue<Runnable> taskQueue = new LinkedBlockingQueue<>(); // 初始化threadB,循环从队列取任务执行 Thread threadB = new Thread(() -> { while (!Thread.currentThread().isInterrupted()) { try { // 队列空时会阻塞,直到有任务进来 Runnable task = taskQueue.take(); task.run(); } catch (InterruptedException e) { // 线程被中断,退出循环 Thread.currentThread().interrupt(); break; } } }); threadB.start(); // 启动threadB
然后修改threadA的代码,把任务放入队列:
Thread threadA = new Thread(() -> { int i = doSomething(); // 把doSomethingElse包装成任务放入队列,threadB会自动处理 try { taskQueue.put(() -> doSomethingElse(i)); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } });
敲黑板提醒
- 不管用哪种方式,程序退出时一定要记得关闭线程池/中断
threadB,避免线程一直占用资源:- 用线程池的话,调用
threadBExecutor.shutdown()(优雅关闭)或threadBExecutor.shutdownNow()(强制关闭); - 手动实现的话,调用
threadB.interrupt()中断线程。
- 用线程池的话,调用
- 如果
doSomethingElse可能抛出异常,建议在任务内部捕获处理,避免threadB因为未捕获异常终止(单线程池会自动重建线程,但手动实现的话线程会直接退出)。
内容的提问来源于stack exchange,提问作者abababab
相关产品推荐
相关产品推荐

