熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> Java編程 >> Java核心技術 >> 正文

使用實時Java降低Java應用程序的易變性(2)

2013-11-23 18:50:56  來源: Java核心技術 

  Java 服務器示例

  在本文剩余部分我們將應用在前面章節中介紹的一些想法使用 Java 類庫中的 Executors 服務構建一個相對簡單的 Java 服務器應用程序只需少量應用程序代碼Executors 服務就可以用於創建一個服務器來管理工作者線程池如清單 所示

  清單 使用 Executors 服務的 Server 和 TaskHandler 類

  import ncurrentExecutors;

  import ncurrentExecutorService;

  import ncurrentThreadFactory;

  class Server {

  private ExecutorService threadPool;

  Server(int numThreads) {

  ThreadFactory theFactory = new ThreadFactory();

  thisthreadPool = ExecutorsnewFixedThreadPool(numThreads theFactory);

  }

  public void start() {

  while (true) {

  // main server handling loop find a task to do

  // create a TaskHandler object to complete this operation

  TaskHandler task = new TaskHandler();

  thisthreadPoolexecute(task);

  }

  thisthreadPoolshutdown();

  }

  public static void main(String[] args) {

  int serverThreads = IntegerparseInt(args[]);

  Server theServer = new Server(serverThreads);

  theServerstart();

  }

  }

  class TaskHandler extends Runnable {

  public void run() {

  // code to handle a task

  }

  }

  此服務器可以創建所有需要的線程直到達到創建服務器(從此示例中的命令行解碼)時指定的最大數量每個工作者線程使用 TaskHandler 類執行一部分工作出於我們的目的我們將創建一個 TaskHandlerrun() 方法它每次運行都應該花相同的時間因此執行 TaskHandlerrun() 的時間上的任何易變性都源自於底層 JVM 中的暫停或易變性某個線程問題或在堆棧的較低級別上引入的暫停清單 給出了 TaskHandler 類

  清單 具有可預測性能的 TaskHandler 類

  import javalangRunnable;

  class TaskHandler implements Runnable {

  static public int N=;

  static public int M=;

  static long result=L;

  // constant work per transaction

  public void run() {

  long dispatchTime = SystemnanoTime();

  long x=L;

  for (int j=;j < M;j++) {

  for (int i=;i < N;i++) {

  x = x + i;

  }

  }

  result = x;

  long endTime = SystemnanoTime();

  ServerreportTiming(dispatchTime endTime);

  }

  }

  此 run() 方法中的循環計算 N () 個整數中前 M () 個整數的和M 和 N 的值已經選定以便運行循環的事務時間為 毫秒左右使一項操作可以被一個 OS 調度限額(通常持續約 毫秒)中斷我們在此計算構造此循環的目的在於使 JIT 編譯器能夠生成將執行高度可預測的時間量的出色代碼run() 方法不會顯式在對 SystemnanoTime() 的兩次調用中顯式阻塞這兩次調用用於計算循環運行的時間由於上述代碼高度可預測所以我們可以使用它來展示延遲和易變性的不一定來源於您測試的代碼

  我們使此應用程序稍微真實一些在運行 TaskHandler 代碼時激活垃圾收集器子系統清單 給出了這個 GCStressThread 類

  清單 用於不斷生成垃圾的 GCStressThread 類

  class GCStressThread extends Thread {

  HashMap<IntegerBinaryTree> map;

  volatile boolean stop = false;

  class BinaryTree {

  public BinaryTree left;

  public BinaryTree right;

  public Long value;

  }

  private void allocateSomeData(boolean useSleep) {

  try {

  for (int i=;i < ;i++) {

  if (useSleep)

  Threadsleep();

  BinaryTree newTree = createNewTree(); // create full level BinaryTree

  thismapput(new Integer(i) newTree);

  }

  } catch (InterruptedException e) {

  stop = true;

  }

  }

  public void initialize() {

  thismap = new HashMap<IntegerBinaryTree>();

  allocateSomeData(false);

  Systemoutprintln(\nFinished initializing\n);

  }

  public void run() {

  while (!stop) {

  allocateSomeData(true);

  }

  }

  }

  GCStressThread 通過 HashMap 維護一組 BinaryTree它為存儲新 BinaryTree 結構的 HashMap 迭代一組相同的 Integer 鍵這些結構是完全填充的 級 BinaryTrees(所以每個 BinaryTree 有 = 個節點被存儲在 HashMap 中)HashMap 在每次迭代時都持有 個 BinaryTree(活動數據)它每隔 毫秒就會將其中一個節點替換為新的 BinaryTree通過這種方式此數據結構維持著一個相當復雜的活動對象集並且以特定速率生成垃圾首先使用 initialize() 例程借助 個 BinaryTree 來初始化HashMapinitialize() 例程不會在對每棵樹的收集之間暫停一旦啟動了 GCStressThread(在啟動服務器之前)它將通過服務器的工作者線程全權處理 TaskHandler 操作

  我們不打算使用客戶端來驅動此服務器我們將直接在服務器的主循環(在 Serverstart() 方法中)中創建 NUM_OPERATIONS == 操作清單 給出了 Serverstart() 方法

  清單 在服務器內部分派操作

  public void start() {

  for (int m=; m < NUM_OPERATIONS;m++) {

  TaskHandler task = new TaskHandler();

  threadPoolexecute(task);

  }

  try {

  while (!serverShutdown) { // boolean set to true when done

  Threadsleep();

  }

  }

  catch (InterruptedException e) {

  }

  }


From:http://tw.wingwit.com/Article/program/Java/hx/201311/25863.html
    推薦文章
    Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.