繁体   English   中英

Java 无法中断其他线程

[英]Java unable to interrupt other threads

我在使用 Java 时遇到了一些问题。我有一个线程 (LparsManager) 生成另一个 class (Poncharello) 的一些其他线程。 问题是 LparsManager 无法中断其他线程。 即使它调用方法 interrupt(),它也无法设置中断标志(我从调试器中看到它)或为孩子抛出中断异常。

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

    }
}

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

        }
    }
}

在我看来,代码应该是中断的。 我试过使用线程 class 进行强制转换,但它不起作用

InterruptedException - 如果任何线程中断了当前线程。 抛出该异常时,当前线程的中断状态被清除。

问题是 LparsManager 无法中断其他线程。 即使它调用方法 interrupt(),也无法设置中断标志...

问题是您对中断的处理:

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

当抛出中断异常时,线程上的中断标志被清除。 如果您查看Thread.sleep(long)方法签名,它说:

 * @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.

所以在catch块中, interrupted()方法总是会返回false。 一旦捕获到InterruptedException ,您就知道线程已被中断,您不需要进行任何额外的测试。 一旦捕获InterruptedException以保留代码调用者的中断状态,重新中断线程实际上是一种正确的模式:

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

此外,您应该使用isInterrupted()方法,因为它不会更改中断标志。 interrupted()方法在调用时清除中断标志。 通常在线程循环中,我会做类似的事情:

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM