新聞中心
一、如下方式存在的問題

成都創(chuàng)新互聯(lián)公司的客戶來自各行各業(yè),為了共同目標,我們在工作上密切配合,從創(chuàng)業(yè)型小企業(yè)到企事業(yè)單位,感謝他們對我們的要求,感謝他們從不同領域給我們帶來的挑戰(zhàn),讓我們激情的團隊有機會用頭腦與智慧不斷的給客戶帶來驚喜。專業(yè)領域包括成都做網(wǎng)站、成都網(wǎng)站設計、電商網(wǎng)站開發(fā)、微信營銷、系統(tǒng)平臺開發(fā)。
- new Thread() {
- @Override
- public void run() {
- // 業(yè)務邏輯
- }
- }.start();
1、首先頻繁的創(chuàng)建、銷毀對象是一個很消耗性能的事情;2、如果用戶量比較大,導致占用過多的資源,可能會導致我們的服務由于資源不足而宕機;3、綜上所述,在實際的開發(fā)中,這種操作其實是不可取的一種方式。
二、使用線程池有什么優(yōu)點
1、線程池中線程的使用率提升,減少對象的創(chuàng)建、銷毀;2、線程池可以控制線程數(shù),有效的提升服務器的使用資源,避免由于資源不足而發(fā)生宕機等問題;
三、線程池的四種使用方式
1、newCachedThreadPool
創(chuàng)建一個線程池,如果線程池中的線程數(shù)量過大,它可以有效的回收多余的線程,如果線程數(shù)不足,那么它可以創(chuàng)建新的線程。
- public static void method() throws Exception {
- ExecutorService executor = Executors.newCachedThreadPool();
- for (int i = 0; i < 5; i++) {
- final int index = i;
- Thread.sleep(1000);
- executor.execute(new Runnable() {
- @Override
- public void run() {
- System.out.println(Thread.currentThread().getName() + " " + index);
- }
- });
- }
- }
執(zhí)行結果
通過分析我看可以看到,至始至終都由一個線程執(zhí)行,實現(xiàn)了線程的復用,并沒有創(chuàng)建多余的線程。如果當我們的業(yè)務需要一定的時間進行處理,那么將會出現(xiàn)什么結果。我們來模擬一下。
可以明顯的看出,現(xiàn)在就需要幾條線程來交替執(zhí)行。
不足:這種方式雖然可以根據(jù)業(yè)務場景自動的擴展線程數(shù)來處理我們的業(yè)務,但是最多需要多少個線程同時處理缺是我們無法控制的;
優(yōu)點:如果當?shù)诙€任務開始,第一個任務已經(jīng)執(zhí)行結束,那么第二個任務會復用第一個任務創(chuàng)建的線程,并不會重新創(chuàng)建新的線程,提高了線程的復用率;
2、newFixedThreadPool
這種方式可以指定線程池中的線程數(shù)。舉個栗子,如果一間澡堂子最大只能容納20個人同時洗澡,那么后面來的人只能在外面排隊等待。如果硬往里沖,那么只會出現(xiàn)一種情景,摩擦摩擦...
首先測試一下最大容量為一個線程,那么會不會是我們預測的結果。
- public static void method_01() throws InterruptedException {
- ExecutorService executor = Executors.newFixedThreadPool(1);
- for (int i = 0; i < 10; i++) {
- Thread.sleep(1000);
- final int index = i;
- executor.execute(() -> {
- try {
- Thread.sleep(2 * 1000);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- System.out.println(Thread.currentThread().getName() + " " + index);
- });
- }
- executor.shutdown();
- }
執(zhí)行結果
我們改為3條線程再來看下結果
優(yōu)點:兩個結果綜合說明,newFixedThreadPool的線程數(shù)是可以進行控制的,因此我們可以通過控制最大線程來使我們的服務器打到最大的使用率,同事又可以保證及時流量突然增大也不會占用服務器過多的資源。
3、newScheduledThreadPool
該線程池支持定時,以及周期性的任務執(zhí)行,我們可以延遲任務的執(zhí)行時間,也可以設置一個周期性的時間讓任務重復執(zhí)行。 該線程池中有以下兩種延遲的方法。
- scheduleAtFixedRate
測試一
- public static void method_02() {
- ScheduledExecutorService executor = Executors.newScheduledThreadPool(5);
- executor.scheduleAtFixedRate(new Runnable() {
- @Override
- public void run() {
- long start = new Date().getTime();
- System.out.println("scheduleAtFixedRate 開始執(zhí)行時間:" +
- DateFormat.getTimeInstance().format(new Date()));
- try {
- Thread.sleep(5000);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- long end = new Date().getTime();
- System.out.println("scheduleAtFixedRate 執(zhí)行花費時間=" + (end - start) / 1000 + "m");
- System.out.println("scheduleAtFixedRate 執(zhí)行完成時間:" + DateFormat.getTimeInstance().format(new Date()));
- System.out.println("======================================");
- }
- }, 1, 5, TimeUnit.SECONDS);
- }
執(zhí)行結果
測試二
總結:以上兩種方式不同的地方是任務的執(zhí)行時間,如果間隔時間大于任務的執(zhí)行時間,任務不受執(zhí)行時間的影響。如果間隔時間小于任務的執(zhí)行時間,那么任務執(zhí)行結束之后,會立馬執(zhí)行,至此間隔時間就會被打亂。
- scheduleWithFixedDelay
測試一
- public static void method_03() {
- ScheduledExecutorService executor = Executors.newScheduledThreadPool(2);
- executor.scheduleWithFixedDelay(new Runnable() {
- @Override
- public void run() {
- long start = new Date().getTime();
- System.out.println("scheduleWithFixedDelay 開始執(zhí)行時間:" +
- DateFormat.getTimeInstance().format(new Date()));
- try {
- Thread.sleep(1000);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- long end = new Date().getTime();
- System.out.println("scheduleWithFixedDelay執(zhí)行花費時間=" + (end - start) / 1000 + "m");
- System.out.println("scheduleWithFixedDelay執(zhí)行完成時間:"
- + DateFormat.getTimeInstance().format(new Date()));
- System.out.println("======================================");
- }
- }, 1, 2, TimeUnit.SECONDS);
- }
執(zhí)行結果
測試二
- public static void method_03() {
- ScheduledExecutorService executor = Executors.newScheduledThreadPool(2);
- executor.scheduleWithFixedDelay(new Runnable() {
- @Override
- public void run() {
- long start = new Date().getTime();
- System.out.println("scheduleWithFixedDelay 開始執(zhí)行時間:" +
- DateFormat.getTimeInstance().format(new Date()));
- try {
- Thread.sleep(5000);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- long end = new Date().getTime();
- System.out.println("scheduleWithFixedDelay執(zhí)行花費時間=" + (end - start) / 1000 + "m");
- System.out.println("scheduleWithFixedDelay執(zhí)行完成時間:"
- + DateFormat.getTimeInstance().format(new Date()));
- System.out.println("======================================");
- }
- }, 1, 2, TimeUnit.SECONDS);
- }
執(zhí)行結果
總結:同樣的,跟scheduleWithFixedDelay測試方法一樣,可以測出scheduleWithFixedDelay的間隔時間不會受任務執(zhí)行時間長短的影響。
4、newSingleThreadExecutor
這是一個單線程池,至始至終都由一個線程來執(zhí)行。
- public static void method_04() {
- ExecutorService executor = Executors.newSingleThreadExecutor();
- for (int i = 0; i < 5; i++) {
- final int index = i;
- executor.execute(() -> {
- try {
- Thread.sleep(2 * 1000);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- System.out.println(Thread.currentThread().getName() + " " + index);
- });
- }
- executor.shutdown();
- }
執(zhí)行結果
四、線程池的作用
線程池的作用主要是為了提升系統(tǒng)的性能以及使用率。文章剛開始就提到,如果我們使用最簡單的方式創(chuàng)建線程,如果用戶量比較大,那么就會產(chǎn)生很多創(chuàng)建和銷毀線程的動作,這會導致服務器在創(chuàng)建和銷毀線程上消耗的性能可能要比處理實際業(yè)務花費的時間和性能更多。線程池就是為了解決這種這種問題而出現(xiàn)的。
同樣思想的設計還有很多,比如數(shù)據(jù)庫連接池,由于頻繁的連接數(shù)據(jù)庫,然而創(chuàng)建連接是一個很消耗性能的事情,所有數(shù)據(jù)庫連接池就出現(xiàn)了。
網(wǎng)頁題目:Java線程池的四種用法與使用場景
瀏覽地址:http://m.5511xx.com/article/cddgocd.html


咨詢
建站咨詢
