Pessoal, nao sei se isso eh avancado propriamente - talvez eu esteja com a solucao na frente do nariz e nao esteja vendo.
Seguinte - imagine que eu tenha um processo que pode ter apenas uma unica thread por vez rodando num determinado processo critico. Mas eu nao quero que as outras threads fiquem esperando - quero que simplesmente encerrem (se eu simplesmente sincronizasse o processo critico e ele demorasse muito, depois eu teria trocentas threads tentando pegar o lock).
Isto posto, pensei no seguinte (obvio):
tenta pegar um lock.
nao conseguiu, return.
caso chegue ate aqui, rodar processo critico.
Porem como saber que a thread nao conseguiu o lock? Ela simplesmente bloqueia, certo?
Entao fiz de outra forma - controlando isso no proprio lock. Ficou meio estranho, entao queria a opiniao de voces se eh isso mesmo, se tem outra forma, se estou viajando, etc.
[code]private static Boolean lock = new Boolean(false);
public void execute() {
synchronized (lock) {
if (lock.booleanValue()) {
return; // existe outra instancia rodando no processo critico
}
lock = new Boolean(true);
}
// processo critico
synchronized (lock) {
lock = new Boolean(false);
}
private String name;
public Runner(String name) {
this.name = name;
}
public void run() {
Processo task = new Processo();
task.initTask(name);
}
public static void main(String[] args) {
Thread t = null;
for (int i = 1; i <= 20; i++) {
t = new Thread(new Runner(String.valueOf(i)));
t.start();
}
}
Interessante que a thread 14 pegou o lock apos a 11 deixa-lo, porem antes da 11 encerrar - isso nao eh problema, pois a 11 ja tinha saido da regiao critica.
Não tem como fazer isso usando o monitor de cada objeto. Tua solução é usar o pacote http://gee.cs.oswego.edu/dl/ util.concurrent do Doug Lea. Ou então o equivamente java.util.concurrent do java 5.0.
Mas lembre de SEMPRE usar try/finally quando adquirir locks. Sempre, sempre, sempre. Ou então o teu código vai ter livelocks. Eu prometo que vai dar pau em produção na madrugada de sabado pra domingo se você não usar try/finally sempre.
Outra coisa, fica a dica de você verificar se não é mais negocio usar futures/executors.
Obrigado Louds. Realmente, usando o Mutex do util.concurrent o codigo ficou mais simples (embora alguem possa argumentar que nao esta no padrao :roll: ):
Claro, em producao fica ainda mais simples, pois um ramo do if eh eliminado e cai fora todos esses prints.
Quanto aos executors, ainda nao sera dessa vez - tenho que me aprofundar nesses “concurrent idioms” para entender toda a potencia do pacote do Doug Lea (e os novos recusos do 1.5 tambem).
Duvida besta: por que tem aquela verificacao se a thread foi interrompida antes de tentar pegar o lock no Mutex do DL? Nao consegui imaginar os efeitos de deixar a thread tentar pegar o lock mesmo ela tendo sido interrompida anteriormente. Eh alguma especie de verificacao de seguranca?
A idéia de interromper uma thread é que ela tome nota do fato o mais rápido possivel. wait() não vai lançar InterruptedException caso a thread já esteja interrompida e isso pode gerar uma demora sem limites por essa notificação.
Essa verificação existe para em um regisme de melhor esforço tentar evitar que aconteça uma pausa indesejada na thread.
Essa é uma preocupação muito importante quando se está usando o mecanismo de interrupt() para tentar minimizar o tempo de resposta, melhorar performânce e até evitar deadlocks.
Hmmm, legal - entao isso eh relacionado com a situacao em questao, certo? (como o Mutex do DL eh generico, a preocupacao eh muito valida)
Nesse processo que estou desenvolvendo nao uso esse mecanismo de interrupcao - vou remover essa verificacao propositalmente (e entao nao precisarei cuidar da excecao). Eh que eu ja tinha lido varias coisas a respeito, mas nao tinha prestado atencao no exato conceito de “interrupcao”, do ponto de vista da classe Thread. Sao interrupcoes geradas apenas por Thread.interrupt - nada de eventos externos, preempcao, etc.