程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> 四種Java線程池用法解析

四種Java線程池用法解析

編輯:關於JAVA

四種Java線程池用法解析。本站提示廣大學習愛好者:(四種Java線程池用法解析)文章只能為提供參考,不一定能成為您想要的結果。以下是四種Java線程池用法解析正文


本文為年夜家剖析四種Java線程池用法,供年夜家參考,詳細內容以下

1、new Thread的弊病

履行一個異步義務你還只是以下new Thread嗎?

new Thread(new Runnable() {

  @Override
  public void run() {
    // TODO Auto-generated method stub
    }
  }
).start();

那你就out太多了,new Thread的弊病以下:

a. 每次new Thread新建對象機能差。
b. 線程缺少同一治理,能夠無窮制新建線程,互相之間競爭,及能夠占用過量體系資本招致逝世機或oom。
c. 缺少更多功效,如准時履行、按期履行、線程中止。

比擬new Thread,Java供給的四種線程池的利益在於:

a. 重用存在的線程,削減對象創立、滅亡的開支,機能佳。
b. 可有用掌握最年夜並發線程數,進步體系資本的應用率,同時防止過量資本競爭,防止梗塞。
c. 供給准時履行、按期履行、單線程、並發數掌握等功效。

2、Java 線程池

Java經由過程Executors供給四種線程池,分離為:

newCachedThreadPool創立一個可緩存線程池,假如線程池長度跨越處置須要,可靈巧收受接管余暇線程,若無可收受接管,則新建線程。
newFixedThreadPool 創立一個定長線程池,可掌握線程最年夜並發數,超越的線程會在隊列中期待。
newScheduledThreadPool 創立一個定長線程池,支撐准時及周期性義務履行。
newSingleThreadExecutor 創立一個單線程化的線程池,它只會用獨一的任務線程來履行義務,包管一切義務依照指定次序(FIFO, LIFO, 優先級)履行。
(1)newCachedThreadPool:

創立一個可緩存線程池,假如線程池長度跨越處置須要,可靈巧收受接管余暇線程,若無可收受接管,則新建線程。示例代碼以下:

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);
}
});
}

線程池為無窮年夜,當履行第二個義務時第一個義務曾經完成,會復用履行第一個義務的線程,而不消每次新建線程。

(2)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();
  }
}
});
}

由於線程池年夜小為3,每一個義務輸入index後sleep 2秒,所以每兩秒打印3個數字。

定長線程池的年夜小最好依據體系資本停止設置。如Runtime.getRuntime().availableProcessors()。可參考PreloadDataCache。

(3)newScheduledThreadPool:

創立一個定長線程池,支撐准時及周期性義務履行。延遲履行示例代碼以下:

ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5);
 scheduledThreadPool.schedule(new Runnable() {

@Override
public void run() {
  System.out.println("delay 3 seconds");
}
}, 3, TimeUnit.SECONDS);

表現延遲3秒履行。

按期履行示例代碼以下:

scheduledThreadPool.scheduleAtFixedRate(new Runnable() {

@Override
public void run() {
  System.out.println("delay 1 seconds, and excute every 3 seconds");
}
}, 1, 3, TimeUnit.SECONDS);

表現延遲1秒後每3秒履行一次。

ScheduledExecutorService比Timer更平安,功效更壯大

(4)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();
    }
}
  });
}

成果順次輸入,相當於次序履行各個義務。

現行年夜多半GUI法式都是單線程的。Android中單線程可用於數據庫操作,文件操作,運用批量裝置,運用批量刪除等不合適並發但能夠IO壅塞性及影響UI線程呼應的操作。

線程池的感化:

線程池感化就是限制體系中履行線程的數目。
根 據體系的情況情形,可以主動或手動設置線程數目,到達運轉的最好後果;少了糟蹋了體系資本,多了形成體系擁堵效力不高。用線程池掌握線程數目,其他線程排 隊等待。一個義務履行終了,再從隊列的中取最後面的義務開端履行。若隊列中沒有期待過程,線程池的這一資本處於期待。當一個新義務須要運轉時,假如線程池 中有期待的任務線程,便可以開端運轉了;不然進入期待隊列。

為何要用線程池:

1.削減了創立和燒毀線程的次數,每一個任務線程都可以被反復應用,可履行多個義務。

2.可以依據體系的蒙受才能,調劑線程池中任務線線程的數量,避免由於消費過量的內存,而把辦事器累爬下(每一個線程須要年夜約1MB內存,線程開的越多,消費的內存也就越年夜,最初逝世機)。

Java外面線程池的頂級接口是Executor,然則嚴厲意義上講Executor其實不是一個線程池,而只是一個履行線程的對象。真實的線程池接口是ExecutorService。

比擬主要的幾個類:

ExecutorService: 真實的線程池接口。

ScheduledExecutorService: 能和Timer/TimerTask相似,處理那些須要義務反復履行的成績。

ThreadPoolExecutor: ExecutorService的默許完成。

ScheduledThreadPoolExecutor: 繼續ThreadPoolExecutor的ScheduledExecutorService接話柄現,周期性義務調劑的類完成。

要設置裝備擺設一個線程池是比擬龐雜的,特別是關於線程池的道理不是很清晰的情形下,很有能夠設置裝備擺設的線程池不是較優的,是以在Executors類外面供給了一些靜態工場,生成一些經常使用的線程池。

1.newSingleThreadExecutor

創立一個單線程的線程池。這個線程池只要一個線程在任務,也就是相當於單線程串行履行一切義務。假如這個獨一的線程由於異常停止,那末會有一個新的線程來替換它。此線程池包管一切義務的履行次序依照義務的提交次序履行。

2.newFixedThreadPool

創立固定年夜小的線程池。每次提交一個義務就創立一個線程,直到線程到達線程池的最年夜年夜小。線程池的年夜小一旦到達最年夜值就會堅持不變,假如某個線程由於履行異常而停止,那末線程池會彌補一個新線程。

3.newCachedThreadPool

創立一個可緩存的線程池。假如線程池的年夜小跨越了處置義務所須要的線程,

那末就會收受接管部門余暇(60秒不履行義務)的線程,當義務數增長時,此線程池又可以智能的添加新線程來處置義務。此線程池不會對線程池年夜小做限制,線程池年夜小完整依附於操作體系(或許說JVM)可以或許創立的最年夜線程年夜小。

4.newScheduledThreadPool

創立一個年夜小無窮的線程池。此線程池支撐准時和周期性履行義務的需求。

實例代碼

1、固定年夜小的線程池,newFixedThreadPool:

package app.executors; 

import java.util.concurrent.Executors; 
import java.util.concurrent.ExecutorService; 

/** 
 * Java線程:線程池 
 * 
 * @author xiho
 */ 
public class Test { 
  public static void main(String[] args) { 
    // 創立一個可重用固定線程數的線程池 
    ExecutorService pool = Executors.newFixedThreadPool(2); 
    // 創立線程 
    Thread t1 = new MyThread(); 
    Thread t2 = new MyThread(); 
    Thread t3 = new MyThread(); 
    Thread t4 = new MyThread(); 
    Thread t5 = new MyThread(); 
    // 將線程放入池中停止履行 
    pool.execute(t1); 
    pool.execute(t2); 
    pool.execute(t3); 
    pool.execute(t4); 
    pool.execute(t5); 
    // 封閉線程池 
    pool.shutdown(); 
  } 
} 

class MyThread extends Thread { 
  @Override 
  public void run() { 
    System.out.println(Thread.currentThread().getName() + "正在履行。。。"); 
  } 
}

輸入成果:

pool-1-thread-1正在履行。。。 
pool-1-thread-3正在履行。。。 
pool-1-thread-4正在履行。。。 
pool-1-thread-2正在履行。。。 
pool-1-thread-5正在履行。。。

轉變ExecutorService pool = Executors.newFixedThreadPool(5)中的參數:ExecutorService pool = Executors.newFixedThreadPool(2),輸入成果是:

pool-1-thread-1正在履行。。。 
pool-1-thread-1正在履行。。。 
pool-1-thread-2正在履行。。。 
pool-1-thread-1正在履行。。。 
pool-1-thread-2正在履行。。。

從以上成果可以看出,newFixedThreadPool的參數指定了可以運轉的線程的最年夜數量,跨越這個數量的線程加出來今後,不會運轉。其次,參加線程池的線程屬於托管狀況,線程的運轉不受參加次序的影響。

2、單義務線程池,newSingleThreadExecutor:

僅僅是把上述代碼中的ExecutorService pool = Executors.newFixedThreadPool(2)改成ExecutorService pool = Executors.newSingleThreadExecutor();
輸入成果:

pool-1-thread-1正在履行。。。 
pool-1-thread-1正在履行。。。 
pool-1-thread-1正在履行。。。 
pool-1-thread-1正在履行。。。 
pool-1-thread-1正在履行。。。

可以看出,每次挪用execute辦法,其實最初都是挪用了thread-1的run辦法。

3、可變尺寸的線程池,newCachedThreadPool:

與下面的相似,只是修改下pool的創立方法:ExecutorService pool = Executors.newCachedThreadPool();

輸入成果:

pool-1-thread-1正在履行。。。 
pool-1-thread-2正在履行。。。 
pool-1-thread-4正在履行。。。 
pool-1-thread-3正在履行。。。 
pool-1-thread-5正在履行。。。

這類方法的特色是:可依據須要創立新線程的線程池,然則在之前結構的線程可用時將重用它們。

4、延遲銜接池,newScheduledThreadPool:

public class TestScheduledThreadPoolExecutor {

  public static void main(String[] args) {

    ScheduledThreadPoolExecutor exec = new ScheduledThreadPoolExecutor(1);

    exec.scheduleAtFixedRate(new Runnable() {//每隔一段時光就觸發異常

           @Override

           publicvoid run() {

              //throw new RuntimeException();

              System.out.println("================");

           }

         }, 1000, 5000, TimeUnit.MILLISECONDS);

    exec.scheduleAtFixedRate(new Runnable() {//每隔一段時光打印體系時光,證實二者是互不影響的

           @Override

           publicvoid run() {

              System.out.println(System.nanoTime());

           }

         }, 1000, 2000, TimeUnit.MILLISECONDS);

  }

}

輸入成果:

================

8384644549516

8386643829034

8388643830710

================

8390643851383

8392643879319

8400643939383

以上就是本文的全體內容,願望對年夜家的進修有所贊助。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved