Depois de descobrir como saber se uma thread conseguiu ou nao um lock (http://www.guj.com.br/posts/list/19700.java), agora estou com um problema mais interessante e desafiador.
Imagine um processo multi-thread que faz requisicoes a um servidor HTTP. Esse processo eh relativamente rapido e nao queremos sobrecarregar o servidor. Dessa forma pensei no seguinte: estabelecer um delay entre uma e outra requisicao. Se isso fosse serial (uma thread), resolveria, mas em paralelo precisa de uma coordenacao entre as threads.
A implementacao ficou assim (o Runner eh o mesmo do topico acima):
[quote=louds]Você quer algo como um lock com efeito retardado? Quem estiver na espera só vai ganhar o lock depois de X segundos que ela for liberada?
Te tal algo assim (adaptado da classe mutex do dl):[/quote]
Otima ideia. Dessa forma a complexidade do gerenciamento de tempo e tal fica tudo na classe do monitor, sendo abstraida do processo que apenas faz uso do monitor.
Porem minha necessidade eh um pouco diferente - um lock com efeito retardado, mas considerando o tempo que o lock anterior gastou. Exemplo: se o delay for de 500 e o processo gastou 100, o proximo lock soh sera liberado apos um wait de 400. Ja se o processo gastou 600, o proximo lock pode ser liberado imediatamente.
Entao ficou assim:
ProcessoDelayMutex (ficou cuti-cuti - como deveria ser):
[code]public class ProcessoDelayMutex {
private static final int DELAY_REQUEST = 500; // em milissegundos
private static final MutexDelay mutex = new MutexDelay(DELAY_REQUEST);
public void initTask() {
try {
mutex.acquire();
doTask();
} catch (Exception e) {
e.printStackTrace();
} finally {
mutex.release();
}
}
private void doTask() throws Exception {
try {
Thread.sleep((long)(Math.random() * 1000));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}[/code]
MutexDelay (adaptacao da tua ideia):
[code]/**
Adaptação do Mutex de Doug Lea para que haja um intervalo mínimo entre a
obtenção dos locks.
*/
public class MutexDelay {
/** Quantidade de milissegundos estabelecida como intervalo mínimo entre um lock e outro. */
private long delay;
/** Status do lock. */
private boolean locked = false;
/** Momento em que o último lock foi obtido. */
private long lockTime = 0;
/** Limite mínimo para a liberação do próximo lock. */
private long nextLockTime = 0;
/**
Construtor da classe. Recebe como parâmetro a quantidade de milissegundos
que deve ser utilizada como intervalo mínimo entre a liberação dos locks.
Libera o lock do monitor.
*/
public synchronized void release() {
long currentTime = System.currentTimeMillis();
long delta = currentTime - this.lockTime;
this.nextLockTime = currentTime;
if (this.delay > delta) {
this.nextLockTime += (this.delay - delta);
}