[英]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.