
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
沒有留言:
張貼留言