天天看點

02.Java基礎(線程池)

執行異步任務的時候,如果隻是new Thread,存在一下弊端

a. 每次new Thread建立對象性能差。
b. 線程缺乏統一管理,可能無限制建立線程,互相之間競争,及可能占用過多系統資源導緻當機或oom。
c. 缺乏更多功能,如定時執行、定期執行、線程中斷。
           

Java本身提供了四種線程池

newCachedThreadPool

建立一個可緩存的線程池。如果線程池的大小超過了處理任務所需要的線程,
那麼就會回收部分空閑(60秒不執行任務)的線程,當任務數增加時,此線程池又可以智
能的添加新線程來處理任務。此線程池不會對線程池大小做限制,線程池大小完全依賴于
作業系統(或者說JVM)能夠建立的最大線程大小。

newCachedThreadPool是存在記憶體溢出安全隐患的,因為我們假設建立的線程都在工
作,newCachedThreadPool 隻會重用空閑并且可用的線程,是以當所需線程數量足夠大
時,會不停地建立新線程,在 64-bit JDK 1.7 中 -Xss 預設是 1024k,也就是 1M(一個線
程占用的空間大小),那就是需要 10000*1M = 10G 的堆外記憶體空間來給線程使用,就 會
發生OOM 

ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
for (int i = 0; i < 10; i++) {
      final int index = i;
try {
      Thread.sleep(index * 1000);
} catch (InterruptedException e) {
      e.printStackTrace();
}
 
cachedThreadPool.execute(new Runnable() {
      @Override
      public void run() {
            System.out.println(index);
      }
});

           
newFixedThreadPool 
建立一個定長線程池,可控制線程最大并發數,超出的線程會在隊列中等待

ExecutorService fixedThreadPool = Executors.newFixedThreadPool(3);
for (int i = 0; i < 10; i++) {
      final int index = i;
      fixedThreadPool.execute(new Runnable() {
 
            @Override
            public void run() {
            try {
                  System.out.println(index);
                  Thread.sleep(2000);
            } catch (InterruptedException e) {
                  // TODO Auto-generated catch block
                  e.printStackTrace();
            }
      }
});
           
newScheduledThreadPool 
建立一個定長線程池,支援定時及周期性任務執行

ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5);
scheduledThreadPool.schedule(new Runnable() {
      @Override
      public void run() {
            System.out.println("delay 3 seconds");
      }
}, 3, TimeUnit.SECONDS);

scheduledThreadPool.scheduleAtFixedRate(new Runnable() {
      @Override
      public void run() {
            System.out.println("delay 1 seconds, and excute every 3 seconds");
      }
}, 1, 3, TimeUnit.SECONDS);
           
newSingleThreadExecutor 
建立一個單線程化的線程池,它隻會用唯一的工作線程來執行任務,保證所有任務按照指定順序(FIFO, LIFO, 優先級)執行

ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();
for (int i = 0; i < 10; i++) {
      final int index = i;
      singleThreadExecutor.execute(new Runnable() {
            @Override
            public void run() {
            try {
                  System.out.println(index);
                  Thread.sleep(2000);
            } catch (InterruptedException e) {
                  // TODO Auto-generated catch block
                  e.printStackTrace();
            }
      }
});

           

相對于直接new Thread,線程池具有一下優點

a. 重用存在的線程,減少對象建立、消亡的開銷,性能佳。
b. 可有效控制最大并發線程數,提高系統資源的使用率,同時避免過多資源競争,避免堵塞。
c. 提供定時執行、定期執行、單線程、并發數控制等功能