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

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

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

先扯再說

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

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

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

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

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

生命周期狀態(tài)

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

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

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

public enum LifecycleState {

  NEW, //新生

  INITIALIZING, INITIALIZED, //初始化

  STARTING, STARTED, //啟動

  SUSPENDING, SUSPENDED, //暫停

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

  DESTROYING, DESTROYED,//銷毀

  FAILED;//失敗

}

接口

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

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也定義了兩個方法可以添加和移除監(jiān)聽者。分別是:public void addLifecycleListener(ILifecycleListener listener);和 public void removeLifecycleListener(ILifecycleListener listener);

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

設(shè)置自身的生命周期狀態(tài)
檢查狀態(tài)的轉(zhuǎn)換是否符合邏輯
通知監(jiān)聽者生命周期狀態(tài)發(fā)生了變化
因此,提供一個抽象類AbstractLifeCycle,作為ILifeCycle的骨架實(shí)現(xiàn)是有重要意義的,這樣避免了很多的重復(fù)代碼,使得架構(gòu)更加清晰。這個抽象類會實(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ī)制。貌似我們可以開始寫一個類來繼承AbstractLifecycle,并重寫其定義的抽象方法了,so far so good。

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

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

例如,我有一個類只需要在初始化,啟動,和銷毀時(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)了一個簡易的生命周期管理機(jī)制,并給出所有的實(shí)現(xiàn)代碼。之后會將所有源代碼放到github上。請關(guān)注本文的update。

相關(guān)文章

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

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

    在Java中實(shí)現(xiàn)大數(shù)據(jù)推薦算法時(shí),通常會使用一些開源的機(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),用戶可以非??焖俚姆绞?,與世界上任何一個角落的網(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ā)成為了一個重要的問題,Spring Boot是一個非常流行的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介紹和使用場景詳解

    Redis介紹和使用場景詳解

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

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

    本文主要對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ì),對大家的學(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ì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-03-03

最新評論

始兴县| 西畴县| 晋中市| 伊吾县| 高安市| 遂平县| 隆昌县| 林州市| 上饶县| 新化县| 抚远县| 白水县| 洛隆县| 明溪县| 鸡泽县| 长子县| 同江市| 天镇县| 广昌县| 乌审旗| 华坪县| 车险| 太谷县| 和林格尔县| 高雄县| 铜鼓县| 涿州市| 兴安盟| 佛学| 明水县| 陈巴尔虎旗| 阳春市| 江西省| 平原县| 五指山市| 宁晋县| 丹江口市| 驻马店市| 宽甸| 久治县| 西昌市|