Java多线程的上下文切换
轉載自?https://blog.csdn.net/fuyuwei2015/article/details/71860349
對于上下文切換不同的操作系統模式也不盡相同,這里我們只討論Unix系統,在我之前的文章中提到過windows的搶占式,這里就不在贅述。?
無論是單核還是多核CPU都是支持多線程代碼的,CPU通過給每個線程分配CPU時間片來實這個機制。時間片是CPU分配給各個線程的時間,因為時間片非常短,所以CPU通過不停地切換線程執行,讓我們感覺多個線程是同時執行的,時間片一般是幾十毫秒(ms)?
CPU通過時間片分配算法來循環執行任務,當前任務執行一個時間片后會切換到下一個任務。但是,在切換前會保存上一個任務的狀態,以便下次切換回這個任務時,可以再加載這個任務的狀態。所以任務從保存到再加載的過程就是一次上下文切換。 很明顯上下文切換會影響多線程的執行速度。
如何減少上線文切換
減少上下文切換的方法有?
1、無鎖并發編程。?
多線程競爭鎖時,會引起上下文切換,所以多線程處理數據時,可以用一?
些辦法來避免使用鎖,如將數據的ID按照Hash算法取模分段,不同的線程處理不同段的數據。?
2、CAS算法。?
Java的Atomic包使用CAS(compare and swap)算法來更新數據,而不需要加鎖。?
3、使用最少線程。避免創建不需要的線程,比如任務很少,但是創建了很多線程來處理,這?
樣會造成大量線程都處于等待狀態。?
4、協程:在單線程里實現多任務的調度,并在單線程里維持多個任務間的切換。
減少上下文切換的例子
下面我們看一個通過減少線上大量WAITING的線程,來減少上下文切換次數的例子:?
使用jstack命令dump線程信息,看看pid為3117的進程里的線程都在做什么
統計所有線程分別處于什么狀態,發現300多個線程處于WAITING(onobjectmonitor)狀態
grep java.lang.Thread.State dump17 | awk '{print $2$3$4$5}' | sort | uniq -c 39 RUNNABLE 21 TIMED_WAITING(onobjectmonitor) 6 TIMED_WAITING(parking) 51 TIMED_WAITING(sleeping) 305 WAITING(onobjectmonitor) 3 WAITING(parking)打開dump文件查看處于WAITING(onobjectmonitor)的線程在做什么。發現這些線程基本全是JBOSS的工作線程,在await。說明JBOSS線程池里線程接收到的任務太少,大量線程都閑著。
"http-0.0.0.0-7001-97" daemon prio=10 tid=0x000000004f6a8000 nid=0x555e in Object.wait() [0x0000000052423000] java.lang.Thread.State: WAITING (on object monitor) at java.lang.Object.wait(Native Method) - waiting on <0x00000007969b2280> (a org.apache.tomcat.util.net.AprEndpoint$Worker) at java.lang.Object.wait(Object.java:485) at org.apache.tomcat.util.net.AprEndpoint$Worker.await(AprEndpoint.java:1464) - locked <0x00000007969b2280> (a org.apache.tomcat.util.net.AprEndpoint$Worker) at org.apache.tomcat.util.net.AprEndpoint$Worker.run(AprEndpoint.java:1489) at java.lang.Thread.run(Thread.java:662)減少JBOSS的工作線程數,找到JBOSS的線程池配置信息,將maxThreads降到100
<maxThreads="250" maxHttpHeaderSize="8192" emptySessionPath="false" minSpareThreads="40" maxSpareThreads="75" maxPostSize="512000" protocol="HTTP/1.1" enableLookups="false" redirectPort="8443" acceptCount="200" bufferSize="16384" connectionTimeout="15000" disableUploadTimeout="false" useBodyEncodingForURI= "true">重啟JBOSS,再dump線程信息,然后統計WAITING(onobjectmonitor)的線程,發現減少了175個。WAITING的線程少了,系統上下文切換的次數就會少,因為每一次從WAITTING到RUNNABLE都會進行一次上下文的切換。讀者也可以使用vmstat命令測試一下。
grep java.lang.Thread.State dump17 | awk '{print $2$3$4$5}' | sort | uniq -c 44 RUNNABLE 22 TIMED_WAITING(onobjectmonitor) 9 TIMED_WAITING(parking) 36 TIMED_WAITING(sleeping) 130 WAITING(onobjectmonitor) 1 WAITING(parking)為什么要減少上下文切換
當CPU從執行一個線程切換到執行另外一個線程的時候,它需要先存儲當前線程的本地的數據,程序指針等,然后載入另一個線程的本地數據,程序指針等,最后才開始執行。這種切換稱為“上下文切換”(“context switch”)。CPU會在一個上下文中執行一個線程,然后切換到另外一個上下文中執行另外一個線程。上下文切換并不廉價,是比較耗時的
總結
以上是生活随笔為你收集整理的Java多线程的上下文切换的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 走进Java中的持有对象(容器类)之一
- 下一篇: java美元兑换,(Java实现) 美元