Home > OS >  Java unable to interrupt other threads
Java unable to interrupt other threads

Time:01-10

I'm getting some problems with Java. I've a thread (LparsManager) that generate some other threads of another class (Poncharello). The problem is that LparsManager is unable to interrupt others thread. Even it calls the method interrupt(), it is unable to set interrupted flag (I've seen it from the debugger) or throw an interrupted exception for childrens.

public class LparsManager extends Thread{

    private int id;

    LparsManager(){
        setName("LparsManager");
        start();
    }

    @Override
    public void run() {

        try {
            Thread.sleep(30000);
        } catch (InterruptedException e) {

        }
        Connection connection=DatabaseManager.connect();
        HashMap<Integer,Poncharello> associazioni=new HashMap<>();
        ArrayList<Integer> al1, al2, al3;
        ResultSet rs=null;

        try {
            //Reperisco il mio id
            rs=connection.createStatement().executeQuery("SELECT id_server FROM "  
                    "servers where hostname='"  InetAddress.getLocalHost().getHostName() "'");
            rs.next();
            id=rs.getInt("id_server");
            ResultSet rs2;

            //Verifico le prime associazioni
            rs=connection.createStatement().executeQuery("SELECT id_lpar FROM "  
                    "lpars where idf_server="  id);
            while (rs.next())
            {
                rs2=connection.createStatement().executeQuery("SELECT CI, IDRS from lpars where id_lpar=" rs.getInt("id_lpar"));
                rs2.next();
                System.out.println("-> " getName() " at " Config.sdf.format(new Timestamp(System.currentTimeMillis())) ": mi è stata assegnata la lpar " rs2.getString("IDRS") 
                        "-" rs2.getString("CI") " da monitorare");
                associazioni.put(rs.getInt("id_lpar"),new Poncharello(rs.getInt("id_lpar"),rs2.getString("IDRS"),rs2.getString("CI")));
            }
            DatabaseManager.close(connection);
        } catch (SQLException | UnknownHostException e) {
            ExceptionManager.sendNotify(e);
            return;
        }

        do {
            //Addormento il thread
            try {
                Thread.sleep(Config.sleep_time);
            } catch (InterruptedException e) {

            }
            al1=new ArrayList<>();
            al2=new ArrayList<>();

            al1.addAll(associazioni.keySet());

            connection=DatabaseManager.connect();

            //Verifico le mie associazioni
            try {

                rs = connection.createStatement().executeQuery("SELECT id_lpar FROM "  
                        "lpars where idf_server="  id);
                while (rs.next())
                {
                    al2.add(rs.getInt("id_lpar"));
                }

                Collections.sort(al1);
                Collections.sort(al2);

                //Se i due Arraylist sono uguali, looppo altrimenti verifico quali lpars aggiungere/rimuovere
                if(!al2.equals(al1))
                {
                    //Verifico quali lpars non sono più da monitorare
                    al3=new ArrayList<>(al1);
                    al3.removeAll(al2);
                    ResultSet rs2;

                    for(Integer a:al3) {

                        associazioni.get(a).interrupt();
                        //tmp.stop();

                        associazioni.remove(a);

                        rs2=connection.createStatement().executeQuery("SELECT CI, IDRS from lpars where id_lpar=" a);
                        rs2.next();

                        System.out.println("-> " getName() " at " Config.sdf.format(new Timestamp(System.currentTimeMillis())) ": mi è stata disassegnata la lpar " rs2.getString("IDRS") 
                                "-" rs2.getString("CI") " da monitorare");
                    }

                    //Verifico quali lpars nuove ho da monitorare
                    al3=new ArrayList<>(al2);
                    al3.removeAll(al1);

                    for(Integer a:al3)
                    {
                        rs2=connection.createStatement().executeQuery("SELECT CI, IDRS from lpars where id_lpar=" a);
                        rs2.next();

                        System.out.println("-> " getName() " at " Config.sdf.format(new Timestamp(System.currentTimeMillis())) ": mi è stata assegnata la lpar " rs2.getString("IDRS") 
                                "-" rs2.getString("CI") " da monitorare");

                        associazioni.put(a,new Poncharello(a,rs2.getString("IDRS"),rs2.getString("CI")));
                    }
                }

            } catch (SQLException e) {
                ExceptionManager.sendNotify(e);
            }

            DatabaseManager.close(connection);

        }while (true);

    }
}

and

public class Poncharello extends Thread{

    private final int idlpar;

    Poncharello(int i, String IDRS, String CI){
        idlpar=i;
        setName("Poncharello " IDRS "-" CI);
        start();
    }

    @Override
    public void run() {
        System.out.println("-> " getName() " at " Config.sdf.format(new Timestamp(System.currentTimeMillis())) ": attività di monitoraggio iniziata");
        while (true)
        {
            try {
                Thread.sleep(10000);
            } catch (InterruptedException e) {
                if(interrupted())
                {
                    System.out.println("-> " getName() " at " Config.sdf.format(new Timestamp(System.currentTimeMillis())) ": mi è stato chiesto di "  
                            "interrompere l'attività di monitoraggio");
                }
            }

            if(interrupted())
            {
                System.out.println("-> " getName() " at " Config.sdf.format(new Timestamp(System.currentTimeMillis())) ": mi è stato chiesto di "  
                        "interrompere l'attività di monitoraggio");
            }

        }
    }
}

In my opinion the code should be interrupt. I've tried withc casting with Thread class but it doesn't work

CodePudding user response:

InterruptedException - if any thread has interrupted the current thread. The interrupted status of the current thread is cleared when this exception is thrown.

CodePudding user response:

The problem is that LparsManager is unable to interrupt others thread. Even it calls the method interrupt(), it is unable to set interrupted flag ...

The problem is your handling of the interrupt:

 try {
      Thread.sleep(10000);
 } catch (InterruptedException e) {
      // interrupt status cleared so this method always returns false
      if (interrupted()) {
            ...

When the interrupted exception is thrown, the interrupt flag on the thread is cleared. If you look at the Thread.sleep(long) method signature, it says:

 * @throws  InterruptedException
 *          if any thread has interrupted the current thread. The
 *          <i>interrupted status</i> of the current thread is
 *          cleared when this exception is thrown.

So in the catch block, the interrupted() method will always return false. Once you have caught InterruptedException you know the thread has been interrupted and you don't need to do any additional tests. It actually is a proper pattern to re-interrupt the thread once you catch InterruptedException to preserve the interrupt status for callers of your code:

 try {
      Thread.sleep(10000);
 } catch (InterruptedException e) {
      // re-interrupt the thread is a good pattern
      Thread.currentThread().interrupt();
      // now handle the interrupt...

Also, you should use the isInterrupted() method because it does not change the interrupt flag. The interrupted() method clears the interrupt flag when called. Typically in a thread loop, I do something like:

while (!Thread.currentThread().isInterrupted()) {
    // do my thread work here
}
  • Related