亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

淺談Java生命周期管理機(jī)制

 更新時(shí)間:2016年01月13日 11:47:25   投稿:hebedich  
最近有位細(xì)心的朋友在閱讀筆者的文章時(shí),對java類的生命周期問題有一些疑惑,筆者打開百度搜了一下相關(guān)的問題,看到網(wǎng)上的資料很少有把這個(gè)問題講明白的,主要是因?yàn)槟壳皣鴥?nèi)java方面的教材大多只是告訴你“怎樣做”,但至于“為什么這樣做”卻不多說

先扯再說

最近一直在研究某個(gè)國產(chǎn)開源的MySQL數(shù)據(jù)庫中間件,拉下其最新版的代碼到eclipse后,啟動起來,然后做各種測試和代碼追蹤;用完想要關(guān)閉它時(shí),拉出它的STOP類想要運(yùn)行時(shí),發(fā)現(xiàn)這個(gè)類里赫然只寫以下幾行代碼,于是我感覺瞬間受到了很多傷害。

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

這個(gè)中間件啟動和運(yùn)行的時(shí)候,開啟了監(jiān)聽,啟動著許多線程在跑著,并且有許多socket連接。但是并沒有找到一個(gè)優(yōu)雅的方式將其關(guān)閉。于是無奈之下,我只能去點(diǎn)eclipse的心碎小紅點(diǎn),強(qiáng)行停掉VM。

如果是一個(gè)架構(gòu)良好,模塊化清晰的軟件,特別是Server類的軟件,擁有一套生命周期管理機(jī)制是非常重要的。不僅可以管理各個(gè)模塊的生命周期,也可以在啟停整個(gè)軟件的時(shí)候更優(yōu)雅,不會漏掉任何資源。

生命周期機(jī)制簡易實(shí)現(xiàn)

生命周期狀態(tài)

一個(gè)模塊的生命周期狀態(tài)一般有以下幾個(gè):

新生 -> 初始化中 -> 初始化完成 -> 啟動中 -> 啟動完成 -> 正在暫停 -> 已經(jīng)暫停 -> 正在恢復(fù) -> 已經(jīng)恢復(fù) -> 正在銷毀 -> 已經(jīng)銷毀
其中,任何一個(gè)狀態(tài)之間的轉(zhuǎn)化如果失敗,那么就會進(jìn)入另外一種狀態(tài):失敗。

為此,可以用一個(gè)枚舉類來枚舉出這幾個(gè)狀態(tài),如下所示:

public enum LifecycleState {

  NEW, //新生

  INITIALIZING, INITIALIZED, //初始化

  STARTING, STARTED, //啟動

  SUSPENDING, SUSPENDED, //暫停

  RESUMING, RESUMED,//恢復(fù)

  DESTROYING, DESTROYED,//銷毀

  FAILED;//失敗

}

接口

生命周期中的各種行為規(guī)范,也需要一個(gè)接口來定義,如下所示:

public interface ILifecycle {

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

  /**
   * 啟動
   * 
   * @throws LifecycleException
   */
  public void start() throws LifecycleException;

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

  /**
   * 恢復(fù)
   * 
   * @throws LifecycleException
   */
  public void resume() throws LifecycleException;

  /**
   * 銷毀
   * 
   * @throws LifecycleException
   */
  public void destroy() throws LifecycleException;

  /**
   * 添加生命周期監(jiān)聽器
   * 
   * @param listener
   */
  public void addLifecycleListener(ILifecycleListener listener);

  /**
   * 刪除生命周期監(jiān)聽器
   * 
   * @param listener
   */
  public void removeLifecycleListener(ILifecycleListener listener);

}

發(fā)生生命周期狀態(tài)轉(zhuǎn)化時(shí),可能需要觸發(fā)對某類事件感興趣的監(jiān)聽者,因此ILifeCycle也定義了兩個(gè)方法可以添加和移除監(jiān)聽者。分別是:public void addLifecycleListener(ILifecycleListener listener);和 public void removeLifecycleListener(ILifecycleListener listener);

監(jiān)聽者也由一個(gè)接口來定義其行為規(guī)范,如下所示:

public interface ILifecycleListener {

  /**
   * 對生命周期事件進(jìn)行處理
   * 
   * @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;
  }

}

骨架實(shí)現(xiàn)

有了ILifeCycle接口以后,任何實(shí)現(xiàn)了這個(gè)接口的類將會被作為一個(gè)生命周期管理對象,這個(gè)類可以是一個(gè)socket監(jiān)聽服務(wù),也可以代表一個(gè)特定的模塊,等等。那我們是不是只要實(shí)現(xiàn)ILifeCycle就可以了? 可以這么說,但考慮到各個(gè)生命周期管理對象在生命周期的各個(gè)階段會有一些共同的行為,比如說:

設(shè)置自身的生命周期狀態(tài)
檢查狀態(tài)的轉(zhuǎn)換是否符合邏輯
通知監(jiān)聽者生命周期狀態(tài)發(fā)生了變化
因此,提供一個(gè)抽象類AbstractLifeCycle,作為ILifeCycle的骨架實(shí)現(xiàn)是有重要意義的,這樣避免了很多的重復(fù)代碼,使得架構(gòu)更加清晰。這個(gè)抽象類會實(shí)現(xiàn)ILifeCycle中定義的所有接口方法,并添加對應(yīng)的抽象方法,供子類實(shí)現(xiàn)。AbstractLifeCycle可以這么實(shí)現(xiàn):

public abstract class AbstractLifecycle implements ILifecycle {

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

  /**
   * state 代表當(dāng)前生命周期狀態(tài)
   */
  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();
  }
}

可以看到,抽象類的骨架實(shí)現(xiàn)中做了幾件生命周期管理中通用的事情,檢查狀態(tài)之間的轉(zhuǎn)換是否合法(比如說start之前必須要init),設(shè)置內(nèi)部狀態(tài),以及觸發(fā)相應(yīng)的監(jiān)聽者。

抽象類實(shí)現(xiàn)了ILifeCycle定義的方法后,又留出了相應(yīng)的抽象方法供其子類實(shí)現(xiàn),如上面的代碼所示,其留出來的抽象方法有以下這些:

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;

優(yōu)雅的實(shí)現(xiàn)

到目前為止,我們已經(jīng)定義了接口ILifeCycle,以及其骨架實(shí)現(xiàn)AbstractLifeCycle,并且增加了監(jiān)聽者機(jī)制。貌似我們可以開始寫一個(gè)類來繼承AbstractLifecycle,并重寫其定義的抽象方法了,so far so good。

但在開始之前,我們還需要考慮另外幾個(gè)問題,

我們的實(shí)現(xiàn)類是否對所有的抽象方法都感興趣?
是否每個(gè)實(shí)現(xiàn)累都需要實(shí)現(xiàn)init0, start0, suspend0, resume0, destroy0?
是否有時(shí)候,我們的那些有生命的類或者模塊并不支持暫停(suspend),恢復(fù)(resume)?
直接繼承AbstractLifeCycle,就意味著必須實(shí)現(xiàn)其全部的抽象方法。
因此,我們還需要一個(gè)默認(rèn)實(shí)現(xiàn),DefaultLifeCycle,讓它繼承AbstractLifeCycle,并實(shí)現(xiàn)所有抽象方法,但它并不做任何實(shí)際的事情, do nothing。只是讓我們真正的實(shí)現(xiàn)類來繼承這個(gè)默認(rèn)的實(shí)現(xiàn)類,并重寫感興趣的方法。

于是,我們的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就是其職責(zé)。
因此接下來我們可以寫一個(gè)自己的實(shí)現(xiàn)類,繼承DefaultLifeCycle,并重寫那些感興趣的生命周期方法。

例如,我有一個(gè)類只需要在初始化,啟動,和銷毀時(shí)做一些任務(wù),那么可以這么寫:

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監(jiān)聽,start0開始獲取socket連接, destroy0銷毀socket監(jiān)聽。
在這套生命周期管理機(jī)制下,我們將會很容易地對資源進(jìn)行管理,不會發(fā)生資源未關(guān)閉的情況,架構(gòu)和模塊化更加清晰。

尾聲

到這里為止,本文已經(jīng)實(shí)現(xiàn)了一個(gè)簡易的生命周期管理機(jī)制,并給出所有的實(shí)現(xiàn)代碼。之后會將所有源代碼放到github上。請關(guān)注本文的update。

相關(guān)文章

  • SpringBoot 多Profile使用與切換方式

    SpringBoot 多Profile使用與切換方式

    這篇文章主要介紹了SpringBoot 多Profile使用與切換方式,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-04-04
  • 關(guān)于服務(wù)網(wǎng)關(guān)Spring Cloud Zuul(Finchley版本)

    關(guān)于服務(wù)網(wǎng)關(guān)Spring Cloud Zuul(Finchley版本)

    這篇文章主要介紹了關(guān)于服務(wù)網(wǎng)關(guān)Spring Cloud Zuul(Finchley版本),具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-03-03
  • Spring Boot使用AOP實(shí)現(xiàn)REST接口簡易靈活的安全認(rèn)證的方法

    Spring Boot使用AOP實(shí)現(xiàn)REST接口簡易靈活的安全認(rèn)證的方法

    這篇文章主要介紹了Spring Boot使用AOP實(shí)現(xiàn)REST接口簡易靈活的安全認(rèn)證的方法,非常具有實(shí)用價(jià)值,需要的朋友可以參考下
    2018-11-11
  • java中List接口與實(shí)現(xiàn)類介紹

    java中List接口與實(shí)現(xiàn)類介紹

    大家好,本篇文章主要講的是java中List接口與實(shí)現(xiàn)類介紹,感興趣的同學(xué)趕快來看一看吧,對你有幫助的話記得收藏一下,方便下次瀏覽
    2021-12-12
  • 深入理解Spring事務(wù)的傳播行為

    深入理解Spring事務(wù)的傳播行為

    Spring在TransactionDefinition接口中規(guī)定了7種類型的事務(wù)傳播行為。下面這篇文章主要給大家介紹了關(guān)于Spring事務(wù)傳播行為的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-02-02
  • IntelliJ IDEA Project窗口的一些設(shè)置詳解

    IntelliJ IDEA Project窗口的一些設(shè)置詳解

    這篇文章主要介紹了IntelliJ IDEA Project窗口的一些設(shè)置詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-08-08
  • Java并發(fā)編程之volatile變量介紹

    Java并發(fā)編程之volatile變量介紹

    這篇文章主要介紹了Java并發(fā)編程之volatile變量介紹,volatile提供了弱同步機(jī)制,用來確保將變量更新通知到其它線程,需要的朋友可以參考下
    2015-04-04
  • 如何優(yōu)雅的拋出Spring Boot注解的異常詳解

    如何優(yōu)雅的拋出Spring Boot注解的異常詳解

    這篇文章主要給大家介紹了關(guān)于如何優(yōu)雅的拋出Spring Boot注解的異常的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2018-12-12
  • SpringBoot實(shí)現(xiàn)跨域的幾種常用方式總結(jié)

    SpringBoot實(shí)現(xiàn)跨域的幾種常用方式總結(jié)

    跨域是指一個(gè)域下的文檔或腳本試圖去請求另一個(gè)域下的資源,或者涉及到兩個(gè)不同域名的資源之間的交互,由于同源策略(Same Origin Policy)的限制,瀏覽器不允許跨域請求,本文小編給大家分享了SpringBoot實(shí)現(xiàn)跨域的幾種常用方式,需要的朋友可以參考下
    2023-09-09
  • Java調(diào)用新浪api通過Ip查詢地區(qū)

    Java調(diào)用新浪api通過Ip查詢地區(qū)

    這篇文章主要介紹了Java調(diào)用新浪接口通過Ip查詢地區(qū),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-05-05

最新評論