查看本機處理器的核心數代碼:Runtime.getRuntime().availableProcessors()
所以,應用程序的最小線程數應該等於可用的處理器核數。如果所有的任務都是計算密集型的,則創建處理器可用的核心數那麼多線程就可以了。在這種情況下,創建更多的線程對程序性能而言反而是不利的。因爲當有多個任務處於就緒狀態時,處理器核心需要在線程間頻繁進行上下文切換,而這種切換對程序性能損耗較大。但如果任務都是IO密集型的,那麼我們就需要開更多的線程來提高性能。
當一個任務執行IO操作時,其線程將被阻塞,於是處理器可以立即進行上下文的切換以便處理其他就緒線程。如果我們只有處理可用核心數那麼多個線程的話,則即使有待執行的任務也無法處理,因爲我們已經拿不出更多的線程供處理器調度了。
如果任務有50%的時間處於阻塞狀態,則程序所需線程數爲處理器可用核心數的兩倍。如果任務被阻塞的時間少於50%,即這些任務是計算密集型的,則程序所需線程數將隨之減少,但最少也不應低於處理器的核心數。如果任務被阻塞的時間大於執行時間,即該任務是IO密集型的,我們就需要創建比處理器核心數大幾倍數量的線程。
線程數=CPU可用核心數/(1-阻塞係數),其中阻塞係數取值0和1之間。
計算密集型任務阻塞係數爲0,而IO密集型任務的阻塞係數接近1。
廢話,不多說了哈!直接上代碼:
package zl;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
/**
* Semaphore還提供一些其他方法:
int availablePermits() :返回此信號量中當前可用的許可證數。
int getQueueLength():返回正在等待獲取許可證的線程數。
boolean hasQueuedThreads() :是否有線程正在等待獲取許可證。
void reducePermits(int reduction) :減少reduction個許可證。是個protected方法。
Collection getQueuedThreads() :返回所有等待獲取許可證的線程集合。是個protected方法。
tryAcquire()方法嘗試獲取許可證
* @author ZL
* 2017年11月26日
*/
public class SemaphoreTest {
private static final int THREAD_COUNT = 30;//總共的線程數
private static ExecutorService threadPool = Executors.newFixedThreadPool(THREAD_COUNT);
private static Semaphore semaphore = new Semaphore(10);//可以併發執行的線程數
public static void main(String[] args) {
for (int i = 0; i < THREAD_COUNT; i++) {
final int j=i;
threadPool.execute(new Runnable() {
public void run() {
try {
semaphore.acquire();//acquire()獲取一個許可證
/**
* 要執行的代碼塊
*/
System.out.println(j+"zl");
semaphore.release();//使用完之後調用release()歸還許可證
} catch (InterruptedException e) {
}
}
});
}
threadPool.shutdown();
}
}