-1

I have a problem with ExecutorService. I have a button in GUI that calls Runnable class that contains ExecutorService. I tried everything to stop ExecutorService (or main thread) but I didn't find a way to end it. Here is my code. Please post your answers and advises. Best regards.

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();
    }
}

Class "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;
}

Sorry here is PingTask class

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 ";";
            }
    }
}
Gray
  • 115,027
  • 24
  • 293
  • 354
ZhiZha
  • 143
  • 2
  • 4
  • 13

3 Answers3

1

Effectively, in order to get threads stopped, each thread within a pooler inialized by ExecutorService must defined a treatment when this one get interrupted.

This is why daemon starting by:

while(true){
}

isn't suitable and is one of the cause of the impossibility of shutdowning the thread pooler.

Prefer for instance:

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

But even with this, you make wonder what it may not work ......

Avoid to swallow InterruptedException!:

catch(InterruptedException e){
//do nothing
}

Indeed, the interrupted flag is cleared when exception is catched ! So don't forget to set it to true by reinpterrupting the thread:

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

For a more detailed explanation, open this link: http://www.ibm.com/developerworks/java/library/j-jtp05236/index.html

Mik378
  • 21,881
  • 15
  • 82
  • 180
0

I guess your PingTask is making URL Connections and connect() call is non interruptible call.

ExecutorService#shutdownNow() offers a way of immediate shutdown by interrupting threads but since these threads can not be interrupted it provides not additional benefit.

It only provides benefit when thread has defined its interruption policy and it performs interruptible operations.

Amit Deshpande
  • 19,001
  • 4
  • 46
  • 72
  • I am not using sockets. I am using ping function. It's ok that program don't kill threads while it ping some ips. I just want to stop doing it (stop doing ExecutorService) . Problem is that I tried and I don't know how to do it... – ZhiZha Sep 27 '12 at 14:19
  • It can not kill them if threads are blocked so your program will never exit.`address.isReachable()` is non interruptible operation – Amit Deshpande Sep 27 '12 at 14:22
  • Hmmm can I stop run method after programs finish ExecutorService? Let's say ThreadPool is 10 and ExecutorService do some pinging and user click "Stop Scan". Can I do someting that will exit run method after first or second ExecutorService is done ? – ZhiZha Sep 27 '12 at 14:25
  • After first run you can do it. – Amit Deshpande Sep 27 '12 at 14:30
  • Cool. it's great. Can you write me a example code how can I do that ? Btw thanks for help – ZhiZha Sep 27 '12 at 14:32
0

Your problem may be that address.isReachable(...) is not interruptible. Interrupting the thread, like @Mik378 mentioned, sets the interrupt bit on the thread and causes some methods (Thread.sleep(), Object.wait(), and others) to throw InterruptedException. The InetAddress.isReachable(...) will not get interrupted unfortunately.

If you are trying to have your print threads finish immediately so the application can exit, you could make them daemon threads. See here:

Making Callable Threads as Daemon

Community
  • 1
  • 1
Gray
  • 115,027
  • 24
  • 293
  • 354