-1

我对 ExecutorService 有疑问。我在 GUI 中有一个按钮,它调用包含 ExecutorService 的 Runnable 类。我尝试了一切来停止 ExecutorService (或主线程),但我没有找到结束它的方法。这是我的代码。请张贴您的答案和建议。此致。

public void actionPerformed(ActionEvent e) {
    final FindGateWaysAndIps scanner = new FindGateWaysAndIps();
    if (e.getActionCommand()=="Start Scan"){
        scanner.start();
    }
    if (e.getActionCommand()=="Stop Scan"){
                scanner.interrupt();
                scanner.stopScans();
    }
}

“FindGateWaysAndIps”类

String ip = "192.168.";
String sql =" ";
static volatile boolean stop = false;
PingResult AllResaults = new PingResult();
int [] AllGateWays = new int [256];

final int NUM_THREADS = Runtime.getRuntime().availableProcessors(); 
ExecutorService exec = Executors.newFixedThreadPool(NUM_THREADS*5);

public void run() {
    stop=true;
    while(stop){
    for (;GateWayKey<=GateWayKeyStop;GateWayKey++){
        if (!stop){
            exec.shutdownNow();
            Thread.currentThread().interrupt();
            break;
        }
        ip="192.168."+GateWayKey+".1";
        AllSQLs.add(exec.submit((new PingTask(ip,GateWayKey,true))));
    }
    if (!stop) {
        exec.shutdownNow();
        Thread.currentThread().interrupt();
        break;
    }
    AllGateWays=GetVectorData.GiveMeGateWays();
    for (int j=0; j<= AllGateWays.length;j++){
        System.out.println("stop je: "+stop);
        if (!stop){
            exec.shutdownNow();
            Thread.currentThread().interrupt();
            break;
        }
        removeDuplicateinVectors();
        //System.out.println("Sada je j"+j);
        for (;SubNetKey<=SubNetKeyStop;SubNetKey++){
            if (!stop){
                exec.shutdownNow();
                Thread.currentThread().interrupt();
                break;
            }
            ip="192.168."+AllGateWays[j]+"."+SubNetKey;         
            AllSQLs.add (exec.submit((new PingTask(ip,AllGateWays[j],false))));
        }

        // Process the result here (this is where you insert into the DB)
        //WriteAllDataIntoDataBase();
    }
    exec.shutdown();
    //WriteAllDataIntoDataBase();
}

public void stopScans(){
    exec.shutdownNow();
    stop=false;
}

抱歉,这里是 PingTask 类

public class PingTask implements Callable <String> {
    String ips;
    String sql;
    PingResult PassDataToExternalClass = new PingResult();
    //FindGateWaysAndIps DataProccesor = new FindGateWaysAndIps();  
    int GateWay;
    ScanFrame MonitorData = new ScanFrame();
    boolean GateWayORSubNet;
    int [] AllGateWays = new int [256];
    int i=0;
    public int[] GiveMeGateWays(){
        return AllGateWays;
    }
    public PingTask (){
    }
    public PingTask (String ip, int GateWayKey, boolean GateWayORSubNets){
        ips=ip;
        GateWay=GateWayKey;
        GateWayORSubNet=GateWayORSubNets;
    }

    public String call(){
        InetAddress address;
        try {
            address = InetAddress.getByName(ips);//ako nade gateway neka skoci u petlju u kojoj nade IP adrese pripadajuceg gatewaya
            System.out.println("PINGAM: "+ips);
            try {
                if (address.isReachable(2000)) { //pinga gatewaya s 1000ms (jeli je moguce ovo smanjiti da se ubrza proces)?
                    System.out.println("Nasa sam IP: "+ips);
                    AllGateWays[i]=GateWay;
                    i++;
                        MonitorData.WriteMonitorData(ips,address.getHostName().toString(),"2000","da");

                    if (GateWayORSubNet){
                            sql="REPLACE INTO `gateways` (`ID_GATEWAY` , `GATEWAY_IP` , `GATEWAY_NAME`) VALUES ('"+GateWay+"', '"+ips+"', '"+address.getHostName().toString()+"');";
                            return sql;
                        }
                        else{
                            sql="REPLACE INTO `subnets` (`IP` , `COMPUTER_NAME` , `GATEWAY_KEY`) VALUES ('"+ips+"', '"+address.getHostName().toString()+"', '"+GateWay+"');";
                            return sql;
                        }
                    } else {
                            return ";";
                    }
                } catch (IOException e) {
                    return ";";
                }
            } catch (UnknownHostException e) {
                return ";";
            }
    }
}
4

3 回答 3

1

实际上,为了使线程停止,由 ExecutorService 初始化的池中的每个线程都必须定义一个在该线程被中断时的处理。

这就是守护进程从以下开始的原因:

while(true){
}

不合适,并且是无法关闭线程池的原因之一。

更喜欢例如:

while(!Thread.currentThread.isInterrupted){
}
//do here what to do in order to exit and clean safely your job and used resources like open filed.

但即使这样,你也会想知道它可能不起作用......

避免吞下 InterruptedException!:

catch(InterruptedException e){
//do nothing
}

事实上,当异常被捕获时,中断标志就会被清除!所以不要忘记通过重新中断线程将其设置为 true:

catch(InterruptedException e){
    Thread.currentThread.interrupt();
}

如需更详细的说明,请打开此链接: http ://www.ibm.com/developerworks/java/library/j-jtp05236/index.html

于 2012-09-27T14:34:39.550 回答
0

您的问题可能address.isReachable(...)是不可中断的。像@Mik378 提到的那样,中断线程会在线程上设置中断位并导致某些方法(Thread.sleep()Object.wait()和其他方法) throw InterruptedException。不幸的是,InetAddress.isReachable(...)不会被打断。

如果您试图让您的打印线程立即完成以便应用程序可以退出,您可以让它们成为守护线程。看这里:

将可调用线程作为守护进程

于 2012-09-27T16:09:55.237 回答
0

我猜您PingTask正在进行 URL 连接,并且 connect() 调用是不可中断的调用。

ExecutorService#shutdownNow()提供了一种通过中断线程立即关闭的方法,但由于这些线程不能被中断,它没有提供额外的好处。

它仅在线程定义了其中断策略并执行可中断操作时才提供好处。

于 2012-09-27T14:09:01.457 回答