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
}