Caros,
Tenho um sistema que precisa executar múltiplas tarefas em parelelo e para isso usei o conceito de pool de threads.
A principio desenvolvi uma solução para atender meus requisitos. Porém estou apanhando para fazer com que cada tarefa execute dentro de um período de timeout ou então seja interrompida.
Segue uma a implementação (obviamente simplificada) para uma possível ajuda.
Este interrupt() não tem efeito sobre a thread em execução, pois a thread a ser interrompida não faz uso de nada da APi de Threads que lance um InterruptedException (ex: Thread.sleep()).
Sei que poderia usar o Thread Pool do Java, com Executor, mas ainda não vi uma forma clara de fazer esse timeout da execução da tarefa.
Sugestões?
package test.thread.pool;
import java.util.ArrayList;
import java.util.List;
public class ThreadPoolTest {
public static void main(String[] args) {
ThreadPoolTest test = new ThreadPoolTest();
test.go();
}
public void go() {
ThreadPool pool = new ThreadPool(10);
pool.start();
}
private class ThreadPool {
private int maxThreads;
private List<MyTask> threads = new ArrayList<MyTask>();
public ThreadPool(int maxThreads) {
this.maxThreads = maxThreads;
}
public void start() {
for( int i=0; i<maxThreads; i++ ) {
MyTask t = new MyTask(threads);
threads.add(t);
t.start();
}
TimeoutEnforcement timeout = new TimeoutEnforcement(threads);
timeout.start();
}
}
private class MyTask extends Thread {
private long start = -1;
private boolean running = false;
private List><MyTask> threads;
public MyTask(List<MyTask> threads) {
this.threads = threads;
}
public void run() {
running = true;
start = System.currentTimeMillis();
int rand = (int) (Math.random() * 10) * 10000;
System.out.println( this.getId()+": "+rand );
try {
process(rand);
System.out.println( this.getId()+": FINISHED" );
} catch(Exception e) {
System.err.println(this.getId()+": error" );
e.printStackTrace();
} finally {
this.threads.remove(this);
running = false;
}
}
public void process(int value) throws InterruptedException {
String a = "";
for(int i=0; i<value; i++) {
a += " ";
// INTERRUPT SÓ FUNCIONA COM ESTA LINHA
//Thread.sleep(1);
}
}
public long getStart() {
return start;
}
public boolean isRunning() {
return running;
}
}
private class TimeoutEnforcement extends Thread {
private List><MyTask> threads;
public TimeoutEnforcement(List<MyTask> threads) {
this.threads = threads;
}
public void run() {
System.out.println("*** TimeoutEnforcement STARTED ***");
while( threads.size() > 0 ) {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
}
System.out.println("*** TimeoutEnforcement RUNNING ***");
for( MyTask t: threads ) {
if( !t.isRunning() || t.getStart()<0 ) {
continue;
}
long now = System.currentTimeMillis();
long elapsed = now - t.getStart();
if( elapsed > 2000 ) {
t.interrupt();
System.out.println("INTERRUPTED: "+t.getId());
}
} //for()
} //while()
System.out.println("*** TimeoutEnforcement FINISHED ***");
}
}
}