Implementar Timout para Método

Olá,

Estou com uma dificuldade meio besta aqui. Preciso implementar um timeout em um método, a execução tem que se interrompida se o método nãor etornar em X segundos.

A solução que pensei foi criar um Command rodando em outra thread e ir checando um atributo que indica se o processamento terminou, mas acho que isso é meio idiota… deve ter um jeito mais simples =/

Segue o código + ou - que estou usando:

//Classe que coordena os requests

public clas Coordena{

 public Subscriber getSubscriber(String string) throws BonusSystemException,
            BlockedTariffIdException {
        Subscriber subscriber = null;

        //prepares the thrreaded request and fires it
        GetSubscriberCommand request = new GetSubscriberCommand(string, system);
        request.execute();

        while (request.isProcessing()) {

            //Decrease the time we will use to sleep
            availableTime -= SLEEP_TIME;

            //If still have some time, sleeps
            if (availableTime > 0)
                try {
                    sleep(SLEEP_TIME);
                } catch (InterruptedException e) {
                    throw new BonusSystemException(e);
                }

        }

        checkRequestStatus(request);

        return  request.getResponse();
    }



private void checkRequestStatus(GetSubscriberCommand request) throws BonusSystemException, BlockedTariffIdException {
        int operationStatus = request.getStatus();

        if (operationStatus != GetSubscriberCommand.SUCCESS) {
            switch (operationStatus) {
            
            case GetSubscriberCommand.ERROR:
                throw (BonusSystemException) request.getException();
            
            case GetSubscriberCommand.BLOCKED:
                throw (BlockedTariffIdException) request.getException();
            
            }
        }
    }



}

Note que o processamento pode gerar dois tipos de exceção, mas como a thread não pode me retorná-las diretamente, estou usando um código de erro ( :evil: ). A classe command é esta:

class GetSubscriberCommand extends Thread {

    private BonusSystem bonusSystem = null;

    private String msisdn = null;

    private Subscriber response = null;

    private boolean processing = false;

    private int status = SUCCESS;

    public static final int SUCCESS = 0;

    public static final int ERROR = 1;

    public static final int BLOCKED = 2;

    private Exception exception = null;

    public boolean isProcessing() {
        return processing;
    }

    public void execute() {
        processing = true;
        try {
            response=bonusSystem.getSubscriber(null, msisdn);
        } catch (BonusSystemException e) {
            status = ERROR;
            exception = e;
        } catch (BlockedTariffIdException e) {
            status = BLOCKED;
            exception = e;
        }
        processing = false;
    }


//getters and setters
}

Alguém tem alguma idéia menos gortesca? É apenas uma operação numa das 3 interfaces do sistema que não pdoe demorar tanto, a solução teria que ser bem simples :frowning:

[]s

Já que é só uma operação, porque não faz um esqueminha simples com flags?

tipo…? :roll:

Contexto:
interface = aplicação web
operação = chamada ejb local ( :evil: ) via business delegate

Detalhe: cada interface tem seu timeout, não posso usar nada que defina um timeout para todos os clientes do EJB (quem tem limite de tempo é a interface, não o bean), Jboss 3.2.x.

[]s

medo
Problema além da minha capacidade.

Contudo, não é o primeiro hehe talvez ajude o primeiro resultado:
http://www.google.com.br/search?hl=pt-BR&client=firefox-a&rls=org.mozilla%3Apt-BR%3Aofficial&q=java+ejb+method+timeout&btnG=Pesquisar&meta=

uhmmmm…nope :frowning:

Não queria usar JTA nem configurar meu bean para isso, queria que a aplicação cliente (no caso a itnerface web) soubesse que o bean está demorando demais (na verdade ela nem sabe que é um bean, ela só chama um método no delegate). Dependendo do tempo gasto, o sistema faz ou não algumas outras tarefas e direciona para uma resposta adequada :frowning:

[]s

Tenta fazer o que vc quer usando transação, e da uma olhada nisso tambem
http://www.onjava.com/pub/a/onjava/2004/10/13/j2ee-timers.html

hmmm
java 1.5? Use java.util.concurrent.
java 1.4? Use o util.concurrent do doug lea.

Use um thread pool (PolledExecutor no d.l.) com futures.

Um future é um handle pra um resultado futuro de uma operação. Eles suportam espera com timeout pelo resultado.

pseudo-código usando o dluc:

       Executor executor = ...
       FutureResult future = new FutureResult();
       Runnable command = future.setter(new Callable() {
          public Object call() { return new BO().chamaMeuEJB(); }
       });
       executor.execute(command);
       future.timedGet(50); //50 ms pra terminar, tolerância zero com EJB lerdo!

1.4

Eu consertei o código acima, funcionando segundo o princípio.

Minha idéia nova era usar wait e notify ao invés desse busy wait bizarro, e uma ThreadPool para evitar a criação de threads cosntantes e com vida curta.

Considerando que isso é para uma operação simples no meio do sistema apenas, acho que importar mais pacotes não vai ser legal.

Perguntas:

  • Que achas do wait/notify?
  • Conehce alguma implementação de ThreadPool simples (uma, duas classes)?

[]s

[quote=pcalcado]

  • Que achas do wait/notify?
  • Conehce alguma implementação de ThreadPool simples (uma, duas classes)?

[]s[/quote]

Boa implementação de thread pool? hmmm, util.concurrent do doug lea?
hehehe

Quanto a usar wait/notify? Eu sei que existem um monte de pegadinhas pra usar de forma eficiente e confiavel.

Minha sugestão? Importe somente as classes do util.concurrent que você vai precisar. Coisa de meia dúzia e se poupe do trabalho de ter que escrever todo esse código e testar.

Todos fontes estão, tirando CopyOnWriteArrayList e ConcurrentReaderHashMap, sob dominio público, então você pode modificar o cabeçalho e por um “@author Shoes” neles que tá tranquilo.