1. 程式人生 > >Java四種執行緒池使用方法

Java四種執行緒池使用方法

1.new Thread的弊端

執行一個非同步任務你還只是如下new Thread嗎?
1234567new Thread(new Runnable() {@Overridepublic void run() {// TODO Auto-generated method stub}}).start();

1-1 說說弊端:

a. 每次new Thread新建物件效能差。
b. 執行緒缺乏統一管理,可能無限制新建執行緒,相互之間競爭,及可能佔用過多系統資源導致宕機或oom。
c. 缺乏更多功能,如定時執行、定期執行、執行緒中斷。

1-2 相比new Thread,Java提供的四種執行緒池的好處在於:

a. 重用存在的執行緒,減少物件建立、消亡的開銷,效能佳。

b. 可有效控制最大併發執行緒數,提高系統資源的使用率,同時避免過多資源競爭,避免堵塞。
c. 提供定時執行、定期執行、單執行緒、併發數控制等功能。

2.Executors提供四種執行緒池

newCachedThreadPool建立一個可快取執行緒池,如果執行緒池長度超過處理需要,可靈活回收空閒執行緒,若無可回收,則新建執行緒。執行緒池的規模不存在限制。
newFixedThreadPool 建立一個固定長度執行緒池,可控制執行緒最大併發數,超出的執行緒會在佇列中等待。
newScheduledThreadPool 建立一個固定長度執行緒池,支援定時及週期性任務執行。

newSingleThreadExecutor 建立一個單執行緒化的執行緒池,它只會用唯一的工作執行緒來執行任務,保證所有任務按照指定順序(FIFO, LIFO, 優先順序)執行。

將執行緒放入執行緒池的兩種方法

2- Executor 介面中的

3.例項

3-1 newCachedThreadPool

package com.th.threadPool;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
 * Created by Administrator on 2018/6/6.
 * newCachedThreadPool建立一個可快取執行緒池,如果執行緒池長度超過處理需要,可靈活回收空閒執行緒,
 * 若無可回收,則新建執行緒。執行緒池的規模不存在限制。
*/ public class NewCachedThreadPool { public static void main(String[] args) { 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(); } //1- 在未來某個時間執行給定的命令。 // 該命令可能在新的執行緒、已入池的執行緒或者正呼叫的執行緒中執行,這由 Executor 實現決定。 cachedThreadPool.execute(new Runnable() { @Override public void run() { System.out.println(index); } }); //2- 提交一個 Runnable 任務用於執行,並返回一個表示該任務的 Future。 // 該 Future 的 get 方法在成功完成時將會返回給定的結果 cachedThreadPool.submit(new Runnable() { @Override public void run() { System.out.println(index); } }); } cachedThreadPool.shutdown(); } }

3-2 newFixedThreadPool

package com.th.threadPool;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
 * Created by Administrator on 2018/6/6.
 *
 * newFixedThreadPool 建立一個固定長度執行緒池,可控制執行緒最大併發數,超出的執行緒會在佇列中等待。
 */
public class NewFixedThreadPool {
    public static void main(String[] args) {
        ExecutorService fixedThreadPool = Executors.newFixedThreadPool(2);
        for (int i = 0; i < 10; i++)
        {
            final int index = i;
//1- 在未來某個時間執行給定的命令。
            // 該命令可能在新的執行緒、已入池的執行緒或者正呼叫的執行緒中執行,這由 Executor 實現決定。
fixedThreadPool.execute(new Runnable() {
                @Override
public void run() {
                    threadRunMethod(index);
}
            });
//2- 提交一個 Runnable 任務用於執行,並返回一個表示該任務的 Future。
            // 該 Future 的 get 方法在成功完成時將會返回給定的結果
fixedThreadPool.submit(new Runnable() {
                @Override
public void run() {
                    threadRunMethod(index);
}
            });
}
        fixedThreadPool.shutdown();
}

    /**
     *
     * @param index
*/
private static void threadRunMethod(int index) {
        try {
            System.out.println(index);
Thread.sleep(2000);
} catch (InterruptedException e) {
            e.printStackTrace();
}
    }
}

3-3 newScheduledThreadPool 
package com.th.threadPool;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
/**
 * Created by Administrator on 2018/6/6.
 * newScheduledThreadPool 建立一個固定長度執行緒池,支援定時及週期性任務執行。
 */
public class NewScheduledThreadPool {
    public static void main(String[] args) {
        ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(5);
//testSchedule(scheduledExecutorService);
        //testScheduleAtFixedRate(scheduledExecutorService);
testScheduleWithFixedDelay(scheduledExecutorService);
// 終止執行緒池
        //scheduledExecutorService.shutdown();
}

    /**
     *
     * 跟 testScheduleAtFixedRate 非常類似,就是延遲的時間有點區別
     * 建立並執行一個在給定初始延遲後首次啟用的定期操作,後續操作具有給定的週期;
     * 也就是將在 initialDelay 後開始執行,然後在 initialDelay+period 後執行,
     * 接著在 initialDelay + 2 * period 後執行,依此類推。
     *
     * 如果任務裡面執行的時間大於 period 的時間,下一次的任務會推遲執行。
     * 推遲的時間 : 等到上次的任務執行完之後再延遲period 的時間後執行。
     * @param scheduledExecutorService
*/
private static void testScheduleWithFixedDelay(ScheduledExecutorService scheduledExecutorService) {
        scheduledExecutorService.scheduleWithFixedDelay(new Runnable() {
            @Override
public void run() {
                try {
                    System.out.println("延遲2秒,再3秒執行一次");
//如果任務裡面執行的時間大於 period 的時間,下一次的任務會推遲執行。
                    //本次任務執行完後下次的任務還需要延遲period時間後再執行
Thread.sleep(6*1000);
} catch (InterruptedException e) {
                    e.printStackTrace();
}
            }
        },2,3,TimeUnit.SECONDS);
}

    /**
     * 建立並執行一個在給定初始延遲後首次啟用的定期操作,後續操作具有給定的週期;
     * 也就是將在 initialDelay 後開始執行,然後在 initialDelay+period 後執行,
     * 接著在 initialDelay + 2 * period 後執行,依此類推。
     *
     * 如果任務裡面執行的時間大於 period 的時間,下一次的任務會推遲執行。
     * 推遲的時間 : 等到上次的任務執行完就立馬執行。
     * @param scheduledExecutorService
*/
private static void testScheduleAtFixedRate(ScheduledExecutorService scheduledExecutorService) {
        scheduledExecutorService.scheduleAtFixedRate(new Runnable() {
            @Override
public void run() {
                try {
                    System.out.println("延遲2秒,再3秒執行一次");
//如果任務裡面執行的時間大於 period 的時間,下一次的任務會推遲執行。
                    //如果任務裡面執行的時間大於 period 的時間,本次任務執行完後,下次任務立馬執行。
Thread.sleep(6*1000);
} catch (InterruptedException e) {
                    e.printStackTrace();
}

            }
        },2,3,TimeUnit.SECONDS);
}

    /**
     * 建立並執行在給定延遲後啟用的一次性操作
     * @param scheduledExecutorService
*/
private static void testSchedule(ScheduledExecutorService scheduledExecutorService) {
        scheduledExecutorService.schedule(new Runnable() {
            @Override
public void run() {
                System.out.println("delay 3 seconds");
}
        }, 3, TimeUnit.SECONDS);
}
}

3-4 newSingleThreadExecutor
package com.th.threadPool;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
 * Created by Administrator on 2018/6/6.
 * newSingleThreadExecutor 建立一個單執行緒化的執行緒池,它只會用唯一的工作執行緒來執行任務,
 * 保證所有任務按照指定順序(FIFO, LIFO, 優先順序)執行。
 */
public class NewSingleThreadExecutor {
    public static void main(String[] args) {

        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("newSingleThreadExecutor: " + index);
                        Thread.sleep(2*1000);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            });*/
singleThreadExecutor.submit(new Runnable() {
                @Override
public void run() {
                    try {
                        System.out.println("newSingleThreadExecutor: " + index);
Thread.sleep(2*1000);
} catch (Exception e) {
                       e.printStackTrace();
}
                }
            });
}

        singleThreadExecutor.shutdown();
}

}