最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

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

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

先扯再說

最近一直在研究某個(gè)國(guó)產(chǎn)開源的MySQL數(shù)據(jù)庫中間件,拉下其最新版的代碼到eclipse后,啟動(dòng)起來,然后做各種測(cè)試和代碼追蹤;用完想要關(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è)中間件啟動(dòng)和運(yùn)行的時(shí)候,開啟了監(jiān)聽,啟動(dòng)著許多線程在跑著,并且有許多socket連接。但是并沒有找到一個(gè)優(yōu)雅的方式將其關(guān)閉。于是無奈之下,我只能去點(diǎn)eclipse的心碎小紅點(diǎn),強(qiáng)行停掉VM。

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

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

生命周期狀態(tài)

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

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

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

public enum LifecycleState {

  NEW, //新生

  INITIALIZING, INITIALIZED, //初始化

  STARTING, STARTED, //啟動(dòng)

  SUSPENDING, SUSPENDED, //暫停

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

  DESTROYING, DESTROYED,//銷毀

  FAILED;//失敗

}

接口

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

public interface ILifecycle {

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

  /**
   * 啟動(dòng)
   * 
   * @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ā)對(duì)某類事件感興趣的監(jiān)聽者,因此ILifeCycle也定義了兩個(gè)方法可以添加和移除監(jiān)聽者。分別是:public void addLifecycleListener(ILifecycleListener listener);和 public void removeLifecycleListener(ILifecycleListener listener);

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

public interface ILifecycleListener {

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

設(shè)置自身的生命周期狀態(tài)
檢查狀態(tài)的轉(zhuǎn)換是否符合邏輯
通知監(jiān)聽者生命周期狀態(tài)發(fā)生了變化
因此,提供一個(gè)抽象類AbstractLifeCycle,作為ILifeCycle的骨架實(shí)現(xiàn)是有重要意義的,這樣避免了很多的重復(fù)代碼,使得架構(gòu)更加清晰。這個(gè)抽象類會(huì)實(shí)現(xiàn)ILifeCycle中定義的所有接口方法,并添加對(duì)應(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)類是否對(duì)所有的抽象方法都感興趣?
是否每個(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
  }

}

對(duì)于DefaultLifeCycle來說,do nothing就是其職責(zé)。
因此接下來我們可以寫一個(gè)自己的實(shí)現(xiàn)類,繼承DefaultLifeCycle,并重寫那些感興趣的生命周期方法。

例如,我有一個(gè)類只需要在初始化,啟動(dòng),和銷毀時(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ī)制下,我們將會(huì)很容易地對(duì)資源進(jìn)行管理,不會(huì)發(fā)生資源未關(guān)閉的情況,架構(gòu)和模塊化更加清晰。

尾聲

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

相關(guān)文章

  • Java中大數(shù)據(jù)推薦算法使用場(chǎng)景分析

    Java中大數(shù)據(jù)推薦算法使用場(chǎng)景分析

    在Java中實(shí)現(xiàn)大數(shù)據(jù)推薦算法時(shí),通常會(huì)使用一些開源的機(jī)器學(xué)習(xí)庫,如Apache Mahout、Weka、DL4J(DeepLearning4j,用于深度學(xué)習(xí))或者Spark MLlib(用于在Spark集群上運(yùn)行),這篇文章主要介紹了Java中可以用的大數(shù)據(jù)推薦算法,需要的朋友可以參考下
    2024-06-06
  • SpringBoot實(shí)現(xiàn)發(fā)送電子郵件

    SpringBoot實(shí)現(xiàn)發(fā)送電子郵件

    這篇文章主要介紹了SpringBoot實(shí)現(xiàn)發(fā)送電子郵件,電子郵件是—種用電子手段提供信息交換的通信方式,是互聯(lián)網(wǎng)應(yīng)用最廣的服務(wù)。通過網(wǎng)絡(luò)的電子郵件系統(tǒng),用戶可以非常快速的方式,與世界上任何一個(gè)角落的網(wǎng)絡(luò)用戶聯(lián)系,下面就來看看SpringBoot如何實(shí)現(xiàn)發(fā)送電子郵件吧
    2022-01-01
  • SpringBoot接口實(shí)現(xiàn)百萬并發(fā)的代碼示例

    SpringBoot接口實(shí)現(xiàn)百萬并發(fā)的代碼示例

    隨著互聯(lián)網(wǎng)的發(fā)展,越來越多的應(yīng)用需要支持高并發(fā),在這種情況下,如何實(shí)現(xiàn)高并發(fā)成為了一個(gè)重要的問題,Spring Boot是一個(gè)非常流行的Java框架,它提供了很多方便的功能來支持高并發(fā),本文將介紹如何使用Spring Boot來實(shí)現(xiàn)百萬并發(fā)
    2023-10-10
  • Spring中常用注解的用法

    Spring中常用注解的用法

    這篇文章主要介紹了Spring中常用注解的用法,Spring注解方式減少了配置文件內(nèi)容,更加便于管理,并且使用注解可以大大提高了開發(fā)效率,注解本身是沒有功能的,和xml一樣,注解和xml都是一種元數(shù)據(jù),元數(shù)據(jù)即解釋數(shù)據(jù)的數(shù)據(jù),也就是所謂的配置,需要的朋友可以參考下
    2023-08-08
  • Redis介紹和使用場(chǎng)景詳解

    Redis介紹和使用場(chǎng)景詳解

    這篇文章主要為大家詳細(xì)介紹了Redis介紹和使用場(chǎng)景,需要的朋友可以參考,具體內(nèi)容如下
    2018-04-04
  • Java編程實(shí)現(xiàn)逆波蘭表達(dá)式代碼示例

    Java編程實(shí)現(xiàn)逆波蘭表達(dá)式代碼示例

    本文主要對(duì)Java算法逆波蘭表達(dá)式的相關(guān)內(nèi)容作了介紹,涉及逆波蘭表達(dá)式的定義已經(jīng)在Java中的實(shí)現(xiàn),具有一定參考價(jià)值,需要的朋友可以了解下。
    2017-10-10
  • java使用dbcp2數(shù)據(jù)庫連接池

    java使用dbcp2數(shù)據(jù)庫連接池

    這篇文章主要為大家詳細(xì)介紹了java使用dbcp2數(shù)據(jù)庫連接池的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2016-10-10
  • Java util.List如何實(shí)現(xiàn)列表分段處理

    Java util.List如何實(shí)現(xiàn)列表分段處理

    這篇文章主要介紹了Java util.List如何實(shí)現(xiàn)列表分段處理,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-09-09
  • Java中的main函數(shù)的詳細(xì)介紹

    Java中的main函數(shù)的詳細(xì)介紹

    這篇文章主要介紹了Java中的main函數(shù)的詳細(xì)介紹的相關(guān)資料,main()函數(shù)在java程序中必出現(xiàn)的函數(shù),這里就講解下使用方法,需要的朋友可以參考下
    2017-09-09
  • 基于Spring的Maven項(xiàng)目實(shí)現(xiàn)發(fā)送郵件功能的示例

    基于Spring的Maven項(xiàng)目實(shí)現(xiàn)發(fā)送郵件功能的示例

    這篇文章主要介紹了基于Spring的Maven項(xiàng)目實(shí)現(xiàn)發(fā)送郵件功能,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-03-03

最新評(píng)論

张北县| 玛多县| 三都| 洛扎县| 蕲春县| 体育| 建始县| 崇州市| 乌拉特前旗| 遂宁市| 宁南县| 昌乐县| 孝义市| 泰州市| 永福县| 蓬溪县| 楚雄市| 方城县| 石家庄市| 阿荣旗| 泾源县| 株洲县| 绿春县| 玉树县| 康乐县| 长寿区| 承德市| 罗城| 皮山县| 安顺市| 县级市| 阜平县| 台安县| 南和县| 灵石县| 南靖县| 福海县| 绵竹市| 灯塔市| 枣阳市| 沾化县|