Java如何为二维数组每行分配线程搜索,找到目标后中断所有运行线程
问题原因与解决方案
原有代码核心问题
- 静态
found变量未加volatile修饰,不保证多线程间的可见性,线程可能读到旧值继续执行 - 静态
id变量是线程不安全的,多个线程实例化时同时自增会出现竞态条件,导致输出的线程ID混乱 - 找到目标值后仅修改标记位,没有主动通知其他线程终止,其余线程需要等到当前循环迭代结束才会感知到标记变化,无法及时停止
- 标记位控制的逻辑本身有延迟,不符合你希望用
interrupt()实现终止的需求
基于interrupt()的修改方案
修改后的Search类
public class Search extends Thread { int low; int high; int[][] array; int threadId; // 存储所有启动的搜索线程,用于后续中断 static Search[] allThreads; public Search(int[][] array, int low, int high, int threadId) { this.array = array; this.high = high; this.low = low; this.threadId = threadId; } public void run(){ // 每层循环都主动检查中断状态,收到中断信号立即退出 for(int i = low; i < high && !isInterrupted(); i++){ for(int j = 0; j < array[i].length && !isInterrupted(); j++){ if(array[i][j] == 0){ System.out.println("Found at: "+i+" "+j + " By thread "+threadId); // 找到后遍历中断所有线程 for (Search t : allThreads) { t.interrupt(); } return; } } } } }
修改后的Main与SearchArray类
public class Main{ public static void main(String[] args){ int[][] array = {{3,0,2,3,0,5},{2,4,0,2,6,5},{4,1,2,4,6,5},{0,2,1,4,0,5},{4,5,6,0,7,1},{9,7,4,1,1,3}}; SearchArray searchArray = new SearchArray(); searchArray.sArray(array); } } class SearchArray{ public void sArray(int[][] array){ int noThreads = array.length; Search[] threads = new Search[noThreads]; // 把线程数组赋值给Search的静态变量,方便找到目标时遍历中断 Search.allThreads = threads; for(int i = 0; i < threads.length; i++){ threads[i] = new Search(array, i, i + 1, i+1); threads[i].start(); } } }
实现说明
- 每个线程在两层循环的判断条件里都主动检查当前线程的中断状态
isInterrupted(),只要收到中断信号就会立刻退出循环,终止执行 - 第一个找到目标值0的线程,会遍历所有启动的搜索线程调用
interrupt()方法,通知所有线程停止运行 - 线程ID改为成员变量,实例化时直接传入,避免静态变量的线程安全问题,输出的ID可以对应到创建的线程顺序
- 不需要额外的标记变量控制,完全基于
interrupt()机制实现终止逻辑,符合需求 - 由于操作系统线程调度顺序不确定,最终输出的第一个找到的0的位置可能有差异,但保证仅输出一次结果,所有线程会在结果输出后立即终止
内容的提问来源于stack exchange,提问作者Rd_x
相关产品推荐
相关产品推荐

