Java无法中断其他线程



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

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

在我看来代码应该是中断的。我试过用线程类铸造,但它不工作

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
}

最新更新