網頁

2014年3月24日 星期一

Memory Leak修復Thread

為了增加執行效率,使用Thread是常見的方法,不過建立Thread也是需要花費昂貴的資源,若沒有限制數量的話,很容易就將內存消耗殆盡,又怎能執行原先欲要處理的商業邏輯,所以使用Thread Pool來修復,消耗過多的資源所造成的Memory Leak內存洩漏。




Mix先建立了2萬條子線程,其內容只是很單純地暫停1秒,主線程則是最後要等待10秒,主要目的是為了給子線程有處理的時間。

package org.openyu.java.memoryleak;

import java.util.concurrent.CompletionService;
import java.util.concurrent.ExecutorCompletionService;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

import org.junit.Test;

/**
 * The Class ThreadLeakTest.
 */
public class ThreadLeakTest {

 /**
  * Thread.
  *
  * @throws Exception
  *             the exception
  */
 @Test
 public void thread() throws Exception {
  int size = 20000; // 2w
  //
  long start = System.currentTimeMillis();
  for (int i = 0; i < size; i++) {
   //
   Thread thread = new Thread(new Runner());
   thread.start();
   System.out.println("create: " + i);
  }
  long end = System.currentTimeMillis();
  //
  Thread.sleep(10 * 1000);
  System.out.println("time: " + (end - start) + " mills.");
 }

 /**
  * The Class Runner.
  */
 protected class Runner implements Runnable {

  /* (non-Javadoc)
   * @see java.lang.Runnable#run()
   */
  public void run() {
   try {
    Thread.sleep(1000);
   } catch (InterruptedException ex) {
   }
  }
 }
}





Mix觀察到,內存發生了OutOfMemoryError。

console顯示建立約到11300條時,就無法繼續,JVM拋出了fatal error,程式無法執行了,就這樣直接掛掉。







因此在內存有限的狀況下,但卻又要建立如此多的子線程時,那麼限制最大數量,將會是一個有效的方式,Mix使用ThreadPoolExecutor來處理資源消耗過多的狀況。


 /**
  * Thread pool executor.
  * 
  * #fix 1
  * 
  * @throws Exception
  *             the exception
  */
 @Test
 public void threadPoolExecutor() throws Exception {
  int size = 20000; // 2w
  //
  ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(100,
    100,
    0L, TimeUnit.MILLISECONDS,
    new LinkedBlockingQueue<Runnable>());

  long start = System.currentTimeMillis();
  for (int i = 0; i < size; i++) {
   //
   Runner runner = new Runner();
   threadPoolExecutor.submit(runner);
   System.out.println("create: " + i);
  }
  long end = System.currentTimeMillis();
  //
  Thread.sleep(10 * 1000);
  System.out.println("time: " + (end - start) + " mills.");
 }



console查看其結果。

create: 19997
create: 19998
create: 19999





另一種修復方式,使用CompletionService來處理,來修復Memory Leak內存洩漏。

 /**
  * Completion service.
  * 
  * #fix 2
  * 
  * @throws Exception
  *             the exception
  */
 @Test
 public void completionService() throws Exception {
  int size = 20000; // 2w
  //
  CompletionService<Object> completionService = new ExecutorCompletionService<Object>(
    Executors.newFixedThreadPool(100));
  //
  long start = System.currentTimeMillis();
  for (int i = 0; i < size; i++) {
   //
   Runner runner = new Runner();
   completionService.submit(runner, null);
   System.out.println("create: " + i);
  }
  long end = System.currentTimeMillis();
  //
  Thread.sleep(10 * 1000);
  System.out.println("time: " + (end - start) + " mills.");
 }



console查看其結果。

create: 19997
create: 19998
create: 19999





也可以用這種修復方式,使用ExecutorService來處理,Memory Leak內存洩漏情況也不再發生了。

 /**
  * Executor service.
  * 
  * #fix 3
  * 
  * @throws Exception
  *             the exception
  */
 @Test
 public void executorService() throws Exception {
  int size = 20000; // 2w
  //
  ExecutorService executorService = Executors.newFixedThreadPool(100);
  //
  long start = System.currentTimeMillis();
  for (int i = 0; i < size; i++) {
   //
   Runner runner = new Runner();
   executorService.submit(runner, null);
   System.out.println("create: " + i);
  }
  long end = System.currentTimeMillis();
  //
  Thread.sleep(10 * 1000);
  System.out.println("time: " + (end - start) + " mills.");
 }



console查看其結果。

create: 19997
create: 19998
create: 19999



沒有留言:

張貼留言

Related Posts Plugin for WordPress, Blogger...