浅谈Java生命周期管理机制_java

先扯再说

最近一直在研究某个国产开源的MySQL数据库中间件,拉下其最新版的代码到eclipse后,启动起来,然后做各种测试和代码追踪;用完想要关闭它时,拉出它的STOP类想要运行时,发现这个类里赫然只写以下几行代码,于是我感觉瞬间受到了很多伤害。

  public static void main(String[] args) {
    System.out.println(new Date() + ",server shutdown!");
  }

这个中间件启动和运行的时候,开启了监听,启动着许多线程在跑着,并且有许多socket连接。但是并没有找到一个优雅的方式将其关闭。于是无奈之下,我只能去点eclipse的心碎小红点,强行停掉VM。

如果是一个架构良好,模块化清晰的软件,特别是Server类的软件,拥有一套生命周期管理机制是非常重要的。不仅可以管理各个模块的生命周期,也可以在启停整个软件的时候更优雅,不会漏掉任何资源。

生命周期机制简易实现

生命周期状态

一个模块的生命周期状态一般有以下几个:

新生 -> 初始化中 -> 初始化完成 -> 启动中 -> 启动完成 -> 正在暂停 -> 已经暂停 -> 正在恢复 -> 已经恢复 -> 正在销毁 -> 已经销毁
其中,任何一个状态之间的转化如果失败,那么就会进入另外一种状态:失败。

为此,可以用一个枚举类来枚举出这几个状态,如下所示:

public enum LifecycleState {

  NEW, //新生

  INITIALIZING, INITIALIZED, //初始化

  STARTING, STARTED, //启动

  SUSPENDING, SUSPENDED, //暂停

  RESUMING, RESUMED,//恢复

  DESTROYING, DESTROYED,//销毁

  FAILED;//失败

}

接口

生命周期中的各种行为规范,也需要一个接口来定义,如下所示:

public interface ILifecycle {

  /**
   * 初始化
   *
   * @throws LifecycleException
   */
  public void init() throws LifecycleException;

  /**
   * 启动
   *
   * @throws LifecycleException
   */
  public void start() throws LifecycleException;

  /**
   * 暂停
   *
   * @throws LifecycleException
   */
  public void suspend() throws LifecycleException;

  /**
   * 恢复
   *
   * @throws LifecycleException
   */
  public void resume() throws LifecycleException;

  /**
   * 销毁
   *
   * @throws LifecycleException
   */
  public void destroy() throws LifecycleException;

  /**
   * 添加生命周期监听器
   *
   * @param listener
   */
  public void addLifecycleListener(ILifecycleListener listener);

  /**
   * 删除生命周期监听器
   *
   * @param listener
   */
  public void removeLifecycleListener(ILifecycleListener listener);

}

发生生命周期状态转化时,可能需要触发对某类事件感兴趣的监听者,因此ILifeCycle也定义了两个方法可以添加和移除监听者。分别是:public void addLifecycleListener(ILifecycleListener listener);和 public void removeLifecycleListener(ILifecycleListener listener);

监听者也由一个接口来定义其行为规范,如下所示:

public interface ILifecycleListener {

  /**
   * 对生命周期事件进行处理
   *
   * @param event 生命周期事件
   */
  public void lifecycleEvent(LifecycleEvent event);
}

生命周期事件由LifecycleEvent来表示,如下所示:

public final class LifecycleEvent {

  private LifecycleState state;

  public LifecycleEvent(LifecycleState state) {
    this.state = state;
  }

  /**
   * @return the state
   */
  public LifecycleState getState() {
    return state;
  }

}

骨架实现

有了ILifeCycle接口以后,任何实现了这个接口的类将会被作为一个生命周期管理对象,这个类可以是一个socket监听服务,也可以代表一个特定的模块,等等。那我们是不是只要实现ILifeCycle就可以了? 可以这么说,但考虑到各个生命周期管理对象在生命周期的各个阶段会有一些共同的行为,比如说:

设置自身的生命周期状态
检查状态的转换是否符合逻辑
通知监听者生命周期状态发生了变化
因此,提供一个抽象类AbstractLifeCycle,作为ILifeCycle的骨架实现是有重要意义的,这样避免了很多的重复代码,使得架构更加清晰。这个抽象类会实现ILifeCycle中定义的所有接口方法,并添加对应的抽象方法,供子类实现。AbstractLifeCycle可以这么实现:

public abstract class AbstractLifecycle implements ILifecycle {

  private List<ILifecycleListener> listeners = new CopyOnWriteArrayList<ILifecycleListener>();

  /**
   * state 代表当前生命周期状态
   */
  private LifecycleState state = LifecycleState.NEW;

  /*
   * @see ILifecycle#init()
   */
  @Override
  public final synchronized void init() throws LifecycleException {
    if (state != LifecycleState.NEW) {
      return;
    }

    setStateAndFireEvent(LifecycleState.INITIALIZING);
    try {
      init0();
    } catch (Throwable t) {
      setStateAndFireEvent(LifecycleState.FAILED);
      if (t instanceof LifecycleException) {
        throw (LifecycleException) t;
      } else {
        throw new LifecycleException(formatString(
            "Failed to initialize {0}, Error Msg: {1}", toString(), t.getMessage()), t);
      }
    }
    setStateAndFireEvent(LifecycleState.INITIALIZED);
  }

  protected abstract void init0() throws LifecycleException;

  /*
   * @see ILifecycle#start()
   */
  @Override
  public final synchronized void start() throws LifecycleException {
    if (state == LifecycleState.NEW) {
      init();
    }

    if (state != LifecycleState.INITIALIZED) {
      return;
    }

    setStateAndFireEvent(LifecycleState.STARTING);
    try {
      start0();
    } catch (Throwable t) {
      setStateAndFireEvent(LifecycleState.FAILED);
      if (t instanceof LifecycleException) {
        throw (LifecycleException) t;
      } else {
        throw new LifecycleException(formatString("Failed to start {0}, Error Msg: {1}",
            toString(), t.getMessage()), t);
      }
    }
    setStateAndFireEvent(LifecycleState.STARTED);
  }

  protected abstract void start0() throws LifecycleException;

  /*
   * @see ILifecycle#suspend()
   */
  @Override
  public final synchronized void suspend() throws LifecycleException {
    if (state == LifecycleState.SUSPENDING || state == LifecycleState.SUSPENDED) {
      return;
    }

    if (state != LifecycleState.STARTED) {
      return;
    }

    setStateAndFireEvent(LifecycleState.SUSPENDING);
    try {
      suspend0();
    } catch (Throwable t) {
      setStateAndFireEvent(LifecycleState.FAILED);
      if (t instanceof LifecycleException) {
        throw (LifecycleException) t;
      } else {
        throw new LifecycleException(formatString("Failed to suspend {0}, Error Msg: {1}",
            toString(), t.getMessage()), t);
      }
    }
    setStateAndFireEvent(LifecycleState.SUSPENDED);
  }

  protected abstract void suspend0() throws LifecycleException;

  /*
   * @see ILifecycle#resume()
   */
  @Override
  public final synchronized void resume() throws LifecycleException {
    if (state != LifecycleState.SUSPENDED) {
      return;
    }

    setStateAndFireEvent(LifecycleState.RESUMING);
    try {
      resume0();
    } catch (Throwable t) {
      setStateAndFireEvent(LifecycleState.FAILED);
      if (t instanceof LifecycleException) {
        throw (LifecycleException) t;
      } else {
        throw new LifecycleException(formatString("Failed to resume {0}, Error Msg: {1}",
            toString(), t.getMessage()), t);
      }
    }
    setStateAndFireEvent(LifecycleState.RESUMED);
  }

  protected abstract void resume0() throws LifecycleException;

  /*
   * @see ILifecycle#destroy()
   */
  @Override
  public final synchronized void destroy() throws LifecycleException {
    if (state == LifecycleState.DESTROYING || state == LifecycleState.DESTROYED) {
      return;
    }

    setStateAndFireEvent(LifecycleState.DESTROYING);
    try {
      destroy0();
    } catch (Throwable t) {
      setStateAndFireEvent(LifecycleState.FAILED);
      if (t instanceof LifecycleException) {
        throw (LifecycleException) t;
      } else {
        throw new LifecycleException(formatString("Failed to destroy {0}, Error Msg: {1}",
            toString(), t.getMessage()), t);
      }
    }
    setStateAndFireEvent(LifecycleState.DESTROYED);
  }

  protected abstract void destroy0() throws LifecycleException;

  /*
   * @see
   * ILifecycle#addLifecycleListener(ILifecycleListener)
   */
  @Override
  public void addLifecycleListener(ILifecycleListener listener) {
    listeners.add(listener);
  }

  /*
   * @see
   * ILifecycle#removeLifecycleListener(ILifecycleListener)
   */
  @Override
  public void removeLifecycleListener(ILifecycleListener listener) {
    listeners.remove(listener);
  }

  private void fireLifecycleEvent(LifecycleEvent event) {
    for (Iterator<ILifecycleListener> it = listeners.iterator(); it.hasNext();) {
      ILifecycleListener listener = it.next();
      listener.lifecycleEvent(event);
    }
  }

  protected synchronized LifecycleState getState() {
    return state;
  }

  private synchronized void setStateAndFireEvent(LifecycleState newState) throws LifecycleException {
    state = newState;
    fireLifecycleEvent(new LifecycleEvent(state));
  }

  private String formatString(String pattern, Object... arguments) {
    return MessageFormat.format(pattern, arguments);
  }

  /*
   * @see java.lang.Object#toString()
   */
  @Override
  public String toString() {
    return getClass().getSimpleName();
  }
}

可以看到,抽象类的骨架实现中做了几件生命周期管理中通用的事情,检查状态之间的转换是否合法(比如说start之前必须要init),设置内部状态,以及触发相应的监听者。

抽象类实现了ILifeCycle定义的方法后,又留出了相应的抽象方法供其子类实现,如上面的代码所示,其留出来的抽象方法有以下这些:

protected abstract void init0() throws LifecycleException;
protected abstract void start0() throws LifecycleException;
protected abstract void suspend0() throws LifecycleException;
protected abstract void resume0() throws LifecycleException;
protected abstract void destroy0() throws LifecycleException;

优雅的实现

到目前为止,我们已经定义了接口ILifeCycle,以及其骨架实现AbstractLifeCycle,并且增加了监听者机制。貌似我们可以开始写一个类来继承AbstractLifecycle,并重写其定义的抽象方法了,so far so good。

但在开始之前,我们还需要考虑另外几个问题,

我们的实现类是否对所有的抽象方法都感兴趣?
是否每个实现累都需要实现init0, start0, suspend0, resume0, destroy0?
是否有时候,我们的那些有生命的类或者模块并不支持暂停(suspend),恢复(resume)?
直接继承AbstractLifeCycle,就意味着必须实现其全部的抽象方法。
因此,我们还需要一个默认实现,DefaultLifeCycle,让它继承AbstractLifeCycle,并实现所有抽象方法,但它并不做任何实际的事情, do nothing。只是让我们真正的实现类来继承这个默认的实现类,并重写感兴趣的方法。

于是,我们的DefaultLifeCycle就这么诞生了:

public class DefaultLifecycle extends AbstractLifecycle {

  /*
   * @see AbstractLifecycle#init0()
   */
  @Override
  protected void init0() throws LifecycleException {
    // do nothing
  }

  /*
   * @see AbstractLifecycle#start0()
   */
  @Override
  protected void start0() throws LifecycleException {
    // do nothing
  }

  /*
   * @see AbstractLifecycle#suspend0()
   */
  @Override
  protected void suspendInternal() throws LifecycleException {
    // do nothing
  }

  /*
   * @see AbstractLifecycle#resume0()
   */
  @Override
  protected void resume0() throws LifecycleException {
    // do nothing
  }

  /*
   * @see AbstractLifecycle#destroy0()
   */
  @Override
  protected void destroy0() throws LifecycleException {
    // do nothing
  }

}

对于DefaultLifeCycle来说,do nothing就是其职责。
因此接下来我们可以写一个自己的实现类,继承DefaultLifeCycle,并重写那些感兴趣的生命周期方法。

例如,我有一个类只需要在初始化,启动,和销毁时做一些任务,那么可以这么写:

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;

public class SocketServer extends DefaultLifecycle {

  private ServerSocket acceptor = null;
  private int port = 9527;
  /*
   * @see DefaultLifecycle#init0()
   */
  @Override
  protected void init0() throws LifecycleException {
    try {
      acceptor = new ServerSocket(port);
    } catch (IOException e) {
      throw new LifecycleException(e);
    }
  }

  /*
   * @see DefaultLifecycle#start0()
   */
  @Override
  protected void start0() throws LifecycleException {
    Socket socket = null;
    try {
      socket = acceptor.accept();
      //do something with socket

    } catch (IOException e) {
      throw new LifecycleException(e);
    } finally {
      if (socket != null) {
        try {
          socket.close();
        } catch (IOException e) {
          // TODO Auto-generated catch block
          e.printStackTrace();
        }
      }
    }
  }

  /*
   * @see DefaultLifecycle#destroy0()
   */
  @Override
  protected void destroy0() throws LifecycleException {
    if (acceptor != null) {
      try {
        acceptor.close();
      } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
      }
    }
  }
}

这里的ServerSocket中,init0初始化socket监听,start0开始获取socket连接, destroy0销毁socket监听。
在这套生命周期管理机制下,我们将会很容易地对资源进行管理,不会发生资源未关闭的情况,架构和模块化更加清晰。

尾声

到这里为止,本文已经实现了一个简易的生命周期管理机制,并给出所有的实现代码。之后会将所有源代码放到github上。请关注本文的update。

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索java
, 生命周期
管理机制
java线程生命周期、java线程的生命周期、java生命周期、java对象的生命周期、java对象生命周期,以便于您获取更多的相关知识。

时间: 2024-08-24 08:23:39

浅谈Java生命周期管理机制_java的相关文章

浅谈Java中的可变参数_java

可变参数 可变参数就是一个方法可以接收任意多个参数!例如:fun().fun(1).fun(1,1).fun(1,1,1).你可能认为这是方法重载,但这不是重载,你想想重载能重载多少个方法,而fun()方法是可以传递任何个数的参数,你能重载这么多个方法么? 2.1 定义可变参数方法 public voidfun(int- arr) {} 上面方法fun()的参数类型为int-,其中"-"不是省略号,而是定义参数类型的方式.参数arr就是可变参数类型.你可以把上面代码理解为:public

浅谈java Collection中的排序问题_java

这里讨论list.set.map的排序,包括按照map的value进行排序. 1)list排序 list排序可以直接采用Collections的sort方法,也可以使用Arrays的sort方法,归根结底Collections就是调用Arrays的sort方法. public static <T> void sort(List<T> list, Comparator<? super T> c) { Object[] a = list.toArray(); Arrays.

浅谈数据库生命周期

最近在读一本<数据库系统 设计.实现与管理>的书,其中的数据库设计部分写的挺好的,另外在本书中也讲到了数据库生命周期的概念,我觉得有所收益,特写下此博文! 在软件开发中,我们经常会提到软件系统开发的生命周期,大致分为:计划.分析.设计.实现.运维几个阶段,整体流程和动作如下图所示: 而针对数据库建模和数据库应用开发来说,也有其自己的"数据库生命周期",database life cycle,简称DBLC.DBLC大致上分为6个阶段:数据库初始研究,数据库设计,实现和装载,测

浅谈Linux的内存管理机制

一 物理内存和虚拟内存 我们知道,直接从物理内存读写数据要比从硬盘读写数据要快的多,因此,我们希望所有数据的读取和写入都在内存完成,而内存是有限的,这样就引出了物理内存与虚拟内存的概念. 物理内存就是系统硬件提供的内存大小,是真正的内存,相对于物理内存,在linux下还有一个虚拟内存的概念,虚拟内存就是为了满足物理内存的不足而提出的策略,它是利用磁盘空间虚拟出的一块逻辑内存,用作虚拟内存的磁盘空间被称为交换空间(Swap Space). 作为物理内存的扩展,linux会在物理内存不足时,使用交换

浅谈Java三大框架与应用_java

前言:对于一个程序员来说,尤其是在java web端开发的程序员,三大框架:Struts+Hibernate+Spring是必须要掌握熟透的,因此,下面谈谈java三大框架的基本概念和原理. JAVA三大框架 一.Spring Spring是一个解决了许多在J2EE开发中常见的问题的强大框架. Spring提供了管理业务对象的一致方法并且鼓励了注入对接口编程而不是对类编程的良好习惯.Spring的架构基础是基于使用JavaBean属性的Inversion of Control容器.然而,这仅仅是

浅谈java实现重载的方法_java

重载(重新载选方法): java允许在一个类中,存在多个方法拥有相同的名字,但在名字相同的同时,必须有不同的参数,这就是重载,编译器会根据实际情况挑选出正确的方法,如果编译器找不到匹配的参数或者找出多个可能的匹配就会产生编译时错误,这个过程被称为重载的解析. 重载包括:普通方法的重载和构造方法的重载 方法:即函数(文中我们统称之为"方法"),是一个固定的一个程序段,或称其为一个子程序,它在可以实现固定运算功能.而且,同时还带有一个入口和一个出口,所谓的入口,就是函数所带的各个参数,我们

浅谈java中Map的用法_java

public interface Map<K,V> 将键映射到值的对象.一个映射不能包含重复的键:每个键最多只能映射到一个值. import javautilHashMap; import javautilMap; public class Test { public static void main(String[] args) { Map map = new HashMap();//声明一个Map mapput("s", "哈哈");//向map中放

浅谈java+内存分配及变量存储位置的区别_java

Java内存分配与管理是Java的核心技术之一,之前我们曾介绍过Java的内存管理与内存泄露以及Java垃圾回收方面的知识,今天我们再次深入Java核心,详细介绍一下Java在内存分配方面的知识.一般Java在内存分配时会涉及到以下区域: ◆寄存器:我们在程序中无法控制 ◆栈:存放基本类型的数据和对象的引用,但对象本身不存放在栈中,而是存放在堆中(new 出来的对象) ◆堆:存放用new产生的数据 ◆静态域:存放在对象中用static定义的静态成员 ◆常量池:存放常量 ◆非RAM存储:硬盘等永久

Java开发平台中的生命周期管理

对象的生命周期没有大家想的那么复杂.其实其就是回答了两个简单的问题.什么时候需要创建对象? 什么时候把对象消亡?这两个问题解决了,那么对象的生命周期问题也就解决了. 一.传统的对象生命周期管理方法. 为了对Java开发平台中的生命周期管理方法有一个更加深刻的理解,笔者认为大家需要对传统的生命 周期管理方法先有一个了解.因为这有助于大家有一个相互的对比,从而会对Java语言中的生命周期管理 方法会有一个比较直观的印象. 在传统的编程语言中,如C语言,其考虑对象的生命周期,主要是从对象与应用程序的执