多執行緒--上下文切換
阿新 • • 發佈:2019-01-27
在開發的過程中,多執行緒一直很受歡迎,因為它的執行速度比序列要快,但是到底快多少呢?一定快麼?下面我們用一段程式碼來測試下
private static final long count = 100000;
public static void main(String[] args) throws InterruptedException {
concurrency();
serial();
}
public static void concurrency() throws InterruptedException{
long start = System.currentTimeMillis();
Thread thread = new Thread(new Runnable() {
public void run() {
int a = 0;
for(long i = 0;i < count;i++){
a += 5;
}
}
});
thread.start();
int b = 0;
for(long i = 0;i < count;i++){
b--;
}
thread.join();
long time = System.currentTimeMillis() - start;
System.out.println("concurrency : " + time + "ms,b = " + b);
}
public static void serial(){
long start = System.currentTimeMillis();
int a = 0;
for(int i=0;i<count;i++){
a += 5;
}
int b = 0;
for(long i = 0;i < count;i++){
b--;
}
long time = System.currentTimeMillis() - start;
System.out.println("serial : " + time + "ms,b = " + b + ",a = " + a);
}
我們來看一些執行結果:
當count = 10000時 輸出:concurrency : 1ms,b = -10000 serial : 0ms,b = -10000,a = 50000
當count = 100000時 輸出:concurrency : 2ms,b = -100000 serial : 3ms,b = -100000,a = 500000
當count = 1000000時 輸出:concurrency : 5ms,b = -1000000 serial : 3ms,b = -1000000,a = 5000000
當count = 10000000時 輸出:concurrency : 7ms,b = -10000000 serial : 11ms,b = -10000000,a = 50000000
當count = 100000000時 輸出:concurrency : 48ms,b = -100000000 serial : 84ms,b = -100000000,a = 500000000
當運算次數越少的時候,序列執行反而比多執行緒快,為什麼會出現這樣的情況?多執行緒為什麼會執行的慢呢?
其實CPU在執行多執行緒的時候時通過給每個執行緒分配CPU時間段來實現多執行緒的,時間片時CPU分配給各個執行緒的時間,因為時間片非常短(一般在幾十毫秒),所以CPU通過不停的切換執行緒執行,才能讓我們感覺到多個執行緒在同時執行。但是CPU線上程之間的切換前要保留上一個執行緒的狀態,同時載入當前執行緒的狀態,在這個操作過程中也就差生了一定的時間消耗。同時沒操作一次,也就完成了一次上下文切換。
如何減少上下文切換?
1、無所併發程式設計。多執行緒競爭鎖才會引起上下文切換,所以多執行緒處理資料時可以儘量避免使用鎖,如不同執行緒處理不同段的資料
2、使用最少執行緒。避免建立不必要的執行緒,避免大量執行緒處於等待狀態
3、協程。在單執行緒裡面實現多工排程,並維持多工之間的切換。