Vamos falar sobre isso primeiro
Recentemente, tenho estudado um middleware de banco de dados MySQL de código aberto doméstico. Depois de retirar sua versão mais recente do código para o Eclipse, iniciá -lo e fazer vários testes e rastreamento de código. Quando quero fechá -lo depois de usá -lo, retiro a aula de parada e quero executá -la. Descobri que apenas as seguintes linhas de código foram escritas nesta classe, então senti que estava muito ferido em um instante.
public static void main (string [] args) {System.out.println (new Date () + ", servidor de desligamento!"); }Quando esse middleware é iniciado e executado, a escuta é ativada, muitos threads são iniciados em execução e há muitas conexões de soquete. Mas não há uma maneira elegante de desligá -lo. Então, em desespero, eu só podia ir ao pequeno ponto vermelho do eclipse e parei com força a VM.
Se é um software com uma boa arquitetura, modularidade e estrutura clara, especialmente um software semelhante ao servidor, é muito importante ter um conjunto de mecanismos de gerenciamento do ciclo de vida. Não apenas pode gerenciar o ciclo de vida de cada módulo, mas também pode ser mais elegante ao iniciar e interromper o software inteiro sem perder nenhum recurso.
Implementação simples do mecanismo do ciclo de vida
Estado do ciclo de vida
O estado do ciclo de vida de um módulo geralmente tem o seguinte:
Recém-nascido-> Inicialização-> Inicialização concluída-> Inicialização-> Inicialização concluída-> Inicialização-> Inicialização-> Parando-> recuperação-> recuperando-> destruindo-> destruindo-> destruindo. Se a conversão entre algum estados falhar, ele entrará em outro estado: falha.
Para fazer isso, você pode usar uma classe de enumeração para enumerar esses estados, como mostrado abaixo:
public Enum Lifecyclestate {new, // Newsen Inicializando, inicializado, // Inicialize Iniciando, iniciado, // Comece a suspender, suspenso, // pausa retomando, retomada, // restaurar, destruir, destruir // Destruir falhou; // falhou}interface
Várias normas comportamentais no ciclo de vida também exigem uma interface para definir, como mostrado abaixo:
interface pública ilifecycle { / ** * Initialize * * @THOWSOWS LIFECYCLYEXCECTION * / public void init () lança LifeCycleException; / ** * START * * @THOWSOWCYCLYEXCECTION */ public void Start () lança LifeCycleException; / ** * pausa * * @THOWSECHECYCLOECCECCETION */ public void suspense () lança LifeCycleException; / ** * Recuperar * * @Throws LifeCycleException */ public void retume () lança LifeCycleException; / ** * Destroy * * @Throws LifeCycleException */ public void Destroy () lança LifeCycleException; / ** * Adicionar ouvinte de ciclo de vida * * @param ouvinte */ public void addlifeCycleListener (ouvinte ilifecycleListener); / ** * Exclua o ouvinte do ciclo de vida * * @param ouvinte */ public void RemovelifeCycleListener (ouvinte ilifecycleListener);}Quando ocorre uma transição de estado do ciclo de vida, os ouvintes interessados em um certo tipo de evento podem precisar ser acionados; portanto, o IlifeCycle também define dois métodos para adicionar e remover os ouvintes. São eles: public void addlifeCycleListener (ouvinte ilifecyclelistener); e o vazio público removelifeCycleListener (ouvinte ilifecyclelistener);
O ouvinte também define suas normas comportamentais por uma interface, como mostrado abaixo:
interface pública ilifecyclelistener { / *** lidera eventos de ciclo de vida** @param eventos de ciclo de vida* / public void LifeCycleEvent (evento LifeCycleEvent);}Os eventos do ciclo de vida são representados pelo LifeCycleEvent, como mostrado abaixo:
Public Final Class Lifecycleevent {Estado Privado Lifecyclestate; public LifeCycleEvent (estado de LifeCyclestate) {this.state = state; } / ** * @RETURN O estado * / public LifeCyclestate getState () {retornar estado; }}Implementação do esqueleto
Com a interface do Ilifecycle, qualquer classe que implementa essa interface será usada como um objeto de gerenciamento do ciclo de vida. Essa classe pode ser um serviço de escuta de soquete, ou pode representar um módulo específico, etc. Então, precisamos apenas implementar o Ilifecycle? Pode -se dizer que, mas considerando que cada objeto de gerenciamento do ciclo de vida terá alguns comportamentos comuns em vários estágios do ciclo de vida, como:
Definir seu próprio estado de ciclo de vida para verificar se a transição do estado está em conformidade com a lógica para notificar o ouvinte de que o estado do ciclo de vida mudou. Portanto, é de grande significado fornecer um resumo abstrato de escala de classe como a implementação do esqueleto do ciclo do Ilife, o que evita muito código duplicado e torna a arquitetura mais clara. Esta classe abstrata implementará todos os métodos de interface definidos no Ilifecycle e adicionará métodos abstratos correspondentes para a implementação da subclasse. AbstractLifeCycle pode ser implementado assim:
classe abstrata public abstractLifecycle implementa o ILIFecycle {Private List <siFecycleListener> ouvintes = novo copywriteArrayList <sipeCyCyListener> (); / *** O estado representa o estado atual do ciclo de vida*/ Estado privado de Lifecyclestate = LifeCyclestate.New; / * * @see ilifeCycle#init () */ @Override Public final sincronizado void init () lança LifeCycleException {if (state! = lifecyclestate.new) {return; } setStateAndFireEvent (LifeCyclestate.initializing); tente {init0 (); } catch (throwable t) {setStateAndfireevent (LifeCyclestate.Failed); if (t instanceof LifeCycleException) {throw (LifeCycleException) t; } else {lança nova LifeCycleException (formatString ("Falha ao inicializar {0}, erro msg: {1}", tostring (), t.getMessage ()), t); }} setStateAndFireevent (LifeCyclestate.initialized); } Resumo protegido void init0 () lança LifeCycleException; / * * @see ilifecycle#start () */ @Override public final sincronizado void start () lança LifeCycleException {if (state == lifecyclestate.new) {init (); } if (state! = lifecyclestate.initialized) {return; } setStateAndFireEvent (LifeCyclestate.Starting); tente {start0 (); } catch (throwable t) {setStateAndfireevent (LifeCyclestate.Failed); if (t instanceof LifeCycleException) {throw (LifeCycleException) t; } else {lança nova LifeCycleException (formatString ("Falha ao iniciar {0}, erro msg: {1}", tostring (), t.getMessage ()), t); }} setStateAndFireevent (LifeCyclestate.started); } Resumo protegido void start0 () lança LifeCycleException; / * * @see ilifeCycle#suspender () */ @Override Public final sincronizado void suspender () lança LifeCycleException {if (state == LIDECYCLESTATE.SUSPENDER || Estado == LIFECYCYCLESTATE.SUSPENDEND) {return; } if (state! = lifecyclestate.started) {return; } setStateAndFireEvent (LifeCyclestate.suspending); tente {suspense0 (); } catch (throwable t) {setStateAndfireevent (LifeCyclestate.Failed); if (t instanceof LifeCycleException) {throw (LifeCycleException) t; } else {lança nova LifeCycleException (formatString ("Falha ao suspender {0}, erro msg: {1}", tostring (), t.getMessage ()), t); }} setStateAndFireevent (LIFECYCLESTATE.SUSPENDEND); } Resumo protegido void suspense0 () lança LifeCycleAxception; / * * @see ilifeCycle#currume () */ @Override public final sincronizado void currume () lança LifeCycleException {if (state! } setStateAndFireEvent (LifeCyclestate.Resuming); tente {currume0 (); } catch (throwable t) {setStateAndfireevent (LifeCyclestate.Failed); if (t instanceof LifeCycleException) {throw (LifeCycleException) t; } else {lança nova LifeCycleException (formatString ("Falha ao retomar {0}, erro msg: {1}", tostring (), t.getMessage ()), t); }} setStateAndFireevent (LIFECYCLESTATE.RESUMED); } Resumo protegido void currume0 () lança LifeCycleAxception; / * * @see ilifeCycle#Destroy () */ @Override Public final Sincronizado void Destroy () lança LifeCycleException {if (state == LIFECYCLESTATE.Destroying || State == LIFECYCYCLESTATE.Destroyed) {return; } setStateAndFireEvent (LifeCyclestate.Destroying); tente {destruir0 (); } catch (throwable t) {setStateAndfireevent (LifeCyclestate.Failed); if (t instanceof LifeCycleException) {throw (LifeCycleException) t; } else {lança nova LifeCycleException (formatString ("falhou ao destruir {0}, erro msg: {1}", tostring (), t.getMessage ()), t); }} setStateAndFireEvent (LifeCyclestate.Destroyed); } Resumo protegido void Destroy0 () lança LifeCycleAxception; / * * @See * ilifeCycle#addLifeCycleListener (ilifeCycleListener) */ @Override public void addlifeCycleListener (ouvinte ilifecycleListener) {ouvintes.add (ouvinte); } / * * @See * ilifeCycle#removeListener (ilifeCycleListener) * / @Override public void removelifeCycleListener (ouvinte ilifecyclelistener) {lideners.remove (ouvinte); } private void FirelifeCycleEvent (Evento LifeCycleEvent) {for (ITERator <ilifeCycleListener> it = ouvintes.iterator (); it.hasNext ();) {ilifeCycLelistener ouvinte = it.next (); ouvinte.lifecycleevent (evento); }} protegido LIFECYCLESTATE SINCRESTATE GETSTATE () {Return State; } private sincronizado void setStateAndFireeEvent (LifeCyclestate NewState) lança LifeCycleAxception {State = NewState; FirelifeCycleEvent (novo LifeCycleEvent (estado)); } private String formatString (padrão da string, objeto ... argumentos) {return messageFormat.format (padrão, argumentos); } / * * @see java.lang.Object#tostring () * / @Override public string tostring () {return getClass (). getSImpleName (); }}Pode -se observar que a implementação do esqueleto de classe abstrata faz várias coisas comuns no gerenciamento do ciclo de vida, verificando se a transição entre estados é legal (por exemplo, deve ser init antes do início), definindo o estado interno e desencadeando o ouvinte correspondente.
Após a classe abstrata, implementa o método definido pelo IlifeCycle, deixa os métodos abstratos correspondentes para sua subclasse implementar. Conforme mostrado no código acima, os métodos abstratos deixados de fora incluem o seguinte:
abstrato protegido void init0 () lança LifeCycleAxception; Resumo protegido void start0 () lança LifeCycleException; Resumo protegido void suspender0 () lança LifeCycleAxception; Resumo Protectado Void Rumume0 () lança LifeCycleAxception; Abstract Protected Void Destroy0 () lança LifeCycleException;
Implementação elegante
Até agora, definimos o Ilifecycy do Ilifecycle da interface, e seu esqueleto implementa o resumo -ciclo e adicionamos um mecanismo do ouvinte. Parece que podemos começar a escrever uma aula para herdar resumo -ciclo e reescrever o método abstrato que ele define, até agora tudo bem.
Mas antes de começarmos, precisamos considerar vários outros problemas.
Nossas classes de implementação estão interessadas em todos os métodos abstratos?
Cada implementação precisa implementar o init0, start0, suspender0, currume0, destruir0, destruir0?
Às vezes, nossas classes ou módulos de vida não suportam suspensão ou recuperação?
A herdadora diretamente de resumo -ciclo significa que todos os seus métodos abstratos devem ser implementados.
Portanto, também precisamos de uma implementação padrão, DefaultLifeCycle, que ele herde o resumo do ciclo e implementamos todos os métodos abstratos, mas não faz nada prático, não fazemos nada. Apenas deixe -nos realizar a classe de implementação herdar essa classe de implementação padrão e substituir o método de interesse.
Então, nasceu nosso DefaultLifeCycle:
public classe DefaultLifeCycle estende a abstraçãoLifeCycle { / * * @See AbstractLifeCycle#init0 () * /@Override Protected void init0 () lança LifeCycleException {// faz nada} / * * @see luminCycle Lifecycle#start0 () * /@Override Protectedad0 () * @see Lifecycle Lifecycle () * /@Override /» AbstractLifeCycle#suspender0 () */ @Override Protected void suspendinternal () lança LifeCycleAxception {// não faz nada}/ * * @see abstratelifecycle#resume0 () */ @override void protegido Remume0 () lança LifeCyclelycrycyclel {// doingride/ * * * * * * * * * * * * * * * *) @override Protected Rerume0 () lança LifeCyclelycry {// doing}/}/ Destroy0 () lança LifeCycleException {// não faz nada}} Para o DefaultLifeCycle, não faça nada é de sua responsabilidade.
Então, em seguida, podemos escrever nossa própria classe de implementação, herdar DefaultLifeCycle e reescrever esses métodos de interesse do ciclo de vida.
Por exemplo, tenho uma aula que só precisa realizar algumas tarefas durante a inicialização, inicialização e destruição, para que eu possa escrever assim:
importar java.io.ioException; importar java.net.serversocket; importar java.net.socket; public class socketServer estende o defaultLifeCycle {private ServerSocket Aceptor = null; private int porta = 9527; / * * @see defaultLifeCycle#init0 () */ @Override Protected void init0 () lança LifeCycleException {try {aceitor = new ServerSocket (porta); } catch (ioexception e) {lança nova LifeCycleException (e); }} / * * @See DefaultLifeCycle#start0 () * / @Override Protected void start0 () lança LifeCycleException {Socket Socket = null; tente {socket = aceitor.accept (); // Faça algo com soquete} catch (ioexception e) {lança nova LifeCycleException (e); } finalmente {if (soquete! = null) {tente {socket.close (); } catch (ioexception e) {// TODO GATO GENERADO AUTOMENTADO BLOCO E.PRINTSTACKTRACE (); }}}}} / * * @see defaultLifeCycle#Destroy0 () * / @Override Protected void Destroy0 () lança LifeCycleException {if (aceitador! = null) {tente {aceitor.close (); } catch (ioexception e) {// TODO GATO GENERADO AUTOMENTADO BLOCO E.PRINTSTACKTRACE (); }}}} No ServerSocket aqui, o init0 inicializa a escuta do soquete, o start0 começa a obter a conexão do soquete, Destroy0 destrói o Socket Heading.
Sob esse mecanismo de gerenciamento do ciclo de vida, gerenciaremos facilmente os recursos e não haverá desligamento de recursos, e a arquitetura e a modularidade serão mais claras.
fim
Até agora, este artigo implementou um mecanismo simples de gerenciamento do ciclo de vida e recebeu todos os códigos de implementação. Depois disso, todo o código -fonte será colocado no GitHub. Por favor, preste atenção à atualização deste artigo.