Ⅰ 如何查看jvm的"active thread
1.一個線程的集合,也可包含其他線程組
2.線程組構成一棵樹,除了初始化線程組外,每一個線程組都有一個父線程組
3.允許線程訪問有關自己的線程組的信息,但不能訪問其父線程組或其他線程組的信息
4.ThreadGroup類只能獲得處於運行狀態的線程
常用方法:
activeCount() 返回線程組中活動線程的估計數
activeGroupCount() 返回線程組中活動線程組的估計數
enumerate(Thread[] list,boolean recurse) 把此線程組中所有活動線程復制到指定數組中
enumerate(ThreadGroup[] list,boolean recurse) 把此線程組中所有活動子組的引用復制到指定的數組中
enumerate(Thread[] list) 把此線程組中所有活動線程復制到指定數組中
enumerate(ThreadGroup[] list) 把此線程組中所有活動子組的引用復制到指定的數組中
getName() 返回此線程組的名稱
getParent() 返回此線程組的父線程組
代碼例子:
package com.xhj.thread;
import java.util.ArrayList;
import java.util.List;
/**
* 查看JVM中的線程 獲取線程名和子線程組
*
* @author XIEHEJUN
*
*/
public class CheckThreadJVM {
/**
* 獲取根線程組
*
* @return
*/
public static ThreadGroup getRootThreadGroup() {
ThreadGroup rootGroup = Thread.currentThread().getThreadGroup();
while (true) {
if (rootGroup.getParent() != null) {
rootGroup = rootGroup.getParent();
} else {
break;
}
}
return rootGroup;
}
/**
* 獲取線程組中的線程名
*
* @param group
* @return
*/
public static List<String> getThreadsName(ThreadGroup group) {
List<String> threadList = new ArrayList<String>();
Thread[] threads = new Thread[group.activeCount()];
int count = group.enumerate(threads, false);
for (int i = 0; i < count; i++) {
threadList.add(group.getName() + "線程組: " + threads[i].getName());
}
return threadList;
}
/**
* 獲取根數組下的子數組
*
* @param group
* @return
*/
public static List<String> getThreadGroup(ThreadGroup group) {
List<String> threadList = getThreadsName(group);
ThreadGroup[] threads = new ThreadGroup[group.activeGroupCount()];
int count = group.enumerate(threads, false);
for (int i = 0; i < count; i++) {
threadList.addAll(getThreadsName(threads[i]));
}
return threadList;
}
public static void main(String[] args) {
for (String string : getThreadGroup(getRootThreadGroup())) {
System.out.println(string);
}
}
}
Ⅱ JVM的線程狀態及如何排查死鎖原因
一般通過查看發生死鎖時當時的內存佔用情況找原因。具體的方式為:通過jmap或者jstat命令導出當前的mp日誌,然後分析日誌中線程執行情況和內存佔用情況。常用命令如下:
// 列印出內存佔用情況
jstat -gcutil 12564 1000 5
// 列印出內存佔用情況
jmap -heap 12564
// 列印出jvm中各個資源佔用情況,比較合適細節查找
jmap -histo 12564 | ./jmap -histo:live 12564 > /home/xxx/jvmmp.txt
// 列印出整個mp的信息(不建議,太復雜)
jmap -mp:format=b,file=/home/xxx/jvmallmp.txt 12564
//列印出各個內存分區的使用情況
jstat -gccapacity 12564
更多細節可以看看這個文章
blog.yemou.net/article/query/info/tytfjhfascvhzxcyt121
Ⅲ 怎麼用linux命令查看jvm進程有幾個線程
在LINUX上可以使用kill -3 pid > thread.info來取得當前JVM線程的信息;
jstack 這個是用來查看jvm當前的thread mp的。可以看到當前Jvm裡面的線程狀況。
這個對於查找blocked線程比較有意義;
Ⅳ jvm優化.有哪些jvm參數用過哪些jvm調優工具
JVM是最好的軟體工程之一,它為Java提供了堅實的基礎,許多流行語言如Kotlin、Scala、Clojure、Groovy都使用JVM作為運行基礎。一個專業的Java工程師必須要了解並掌握JVM,接下來就給大家分享Java基礎知識中JVM調優相關知識點。
杭州Java基礎知識學習之JVM調優講解
JVM常見的調優參數包括:
-Xmx:指定java程序的最大堆內存, 使用java -Xmx5000M -version判斷當前系統能分配的最大堆內存;
-Xms:指定最小堆內存, 通常設置成跟最大堆內存一樣,減少GC;
-Xmn:設置年輕代大小。整個堆大小=年輕代大小+年老代大小。所以增大年輕代後,將會減小年老代大小。此值對系統性能影響較大,Sun官方推薦配置為整個堆的3/8;
-Xss:指定線程的最大棧空間, 此參數決定了java函數調用的深度, 值越大調用深度越深, 若值太小則容易出棧溢出錯誤(StackOverflowError);
-XX:PermSize:指定方法區(永久區)的初始值,默認是物理內存的1/64,在Java8永久區移除, 代之的是元數據區,由-XX:MetaspaceSize指定;
-XX:MaxPermSize:指定方法區的最大值, 默認是物理內存的1/4,在java8中由-XX:MaxMetaspaceSize指定元數據區的大小;
-XX:NewRatio=n:年老代與年輕代的比值,-XX:NewRatio=2, 表示年老代與年輕代的比值為2:1;
-XX:SurvivorRatio=n:Eden區與Survivor區的大小比值,-XX:SurvivorRatio=8表示Eden區與Survivor區的大小比值是8:1:1,因為Survivor區有兩個(from, to)。
JVM實質上分為三大塊,年輕代(YoungGen),年老代(Old Memory),及持久代(Perm,在Java8中被取消)。
年輕代大小選擇
響應時間優先的應用:盡可能設大,直到接近系統的最低響應時間限制(根據實際情況選擇)。在此種情況下,年輕代收集發生的頻率也是最小的。同時,減少到達年老代的對象。
吞吐量優先的應用:盡可能的設置大,可能到達Gbit的程度。因為對響應時間沒有要求,垃圾收集可以並行進行,一般適合8CPU以上的應用。
年老代大小選擇
響應時間優先的應用:年老代使用並發收集器,所以其大小需要小心設置,一般要考慮並發會話率和會話持續時間等一些參數。如果堆設置小了,可以會造成內存碎片、高回收頻率以及應用暫停而使用傳統的標記清除方式;如果堆大了,則需要較長的收集時間。最優化的方案,一般需要參考以下數據獲得:並發垃圾收集信息、持久代並發收集次數、傳統GC信息、花在年輕代和年老代回收上的時間比例。
減少年輕代和年老代花費的時間,一般會提高應用的效率。
吞吐量優先的應用:一般吞吐量優先的應用都有一個很大的年輕代和一個較小的年老代。原因是,這樣可以盡可能回收掉大部分短期對象,減少中期的對象,而年老代盡存放長期存活對象。
較小堆引起的碎片問題
因為年老代的並發收集器使用標記、清除演算法,所以不會對堆進行壓縮。當收集器回收時,他會把相鄰的空間進行合並,這樣可以分配給較大的對象。但是,當堆空間較小時,運行一段時間以後,就會出現「碎片」,如果並發收集器找不到足夠的空間,那麼並發收集器將會停止,然後使用傳統的標記、清除方式進行回收。如果出現「碎片」,可能需要進行如下配置:
-XX:+UseCMSCompactAtFullCollection:使用並發收集器時,開啟對年老代的壓縮。
-XX:CMSFullGCsBeforeCompaction=0:上面配置開啟的情況下,這里設置多少次Full GC後,對年老代進行壓縮。
Ⅳ java中多線程常見的幾個參數
java中多線程常見的幾個參數
sleep:在指定的毫秒數內讓當前正在執行的線程休眠(暫停執行).
此操作受到系統計時器和調度程序精度和准確性的影響。
該線程不丟失任何監視器的所屬權。
調用sleep的時候鎖並沒有被釋放。
休眠
Java SE5引入了更加顯示的sleep()作為TimeUnit類的一部分,這個方法允許你指定sleep()延遲的時間單元,因此可以提供更好的可閱讀性。
wait:調用wait使線程掛起,直到線程得到了notify或notifyAll消息,線程才會進入就緒狀態。
使你可以等待某個條件發生變化,而改變這個條件超出了當前方法的控制能力。
線程的執行被掛起,對象上的鎖被釋放。意味著另一個任務可以獲得這個鎖。
因此在該對象中的其他synchronized方法可以在wait期間被調用。
yield:相當於:我的工作已經做的差不多了,可以讓給別的線程使用CPU了。
當調用yield時,你也是在建議具有相同優先順序的其他線程可以運行。
對於任何重要的控制或在調整應用時,都不能依賴於yield。
yield並不意味著退出和暫停,只是,告訴線程調度如果有人需要,可以先拿去,我過會再執行,沒人需要,我繼續執行
調用yield的時候鎖並沒有被釋放。
interrupt:中斷線程。
Thread類包含interrupt()方法,因此你可以中止被阻塞的任務。
這個方法將設置線程的中斷狀態。
如果一個線程已經被阻塞,或者試圖執行一個阻塞操作,那麼設置這個線程的中斷狀態將拋出InterruptedException。
當拋出該異常或者該任何調用Thread.interrupted()時,中斷狀態將復位。
你在Executor上調用shutdownNow(),那麼它將發送一個interrupt()調用給他啟動的所有線程。
Ⅵ JVM調優jstack怎麼找出最耗cpu的線程並定位代碼
第一步:先找出java的進程Id(PID) 假設java應用名稱是zcg_commodity
ps -ef|grep zcg_commodity
得到進程Id為32464
第二步:找出該進程內最消耗CPU的線程
top -Hp pid
輸入top -Hp 32464
TIME列就是各個java線程耗費的CPU的時間,比如圖中是線程ID的為2012的線程,
通過 printf 「%x\n」 2012
得到2012的十六進制為 7dc
第三步:
一般會進到jdk的bin目錄下,root許可權執行
jstack 32464|grep 7dc
Ⅶ java線程的幾個概念和方法
新建狀態:用new語句創建的線程對象處於新建狀態,此時它和其它的java對象一樣,僅僅在堆中被分配了內存 就緒狀態:當一個線程創建了以後,其他的線程調用了它的start()方法,該線程就進入了就緒狀態。處於這個狀態的線程位於可運行池中,等待獲得CPU的使用權
運行狀態:處於這個狀態的線程佔用CPU,執行程序的代碼
阻塞狀態:當線程處於阻塞狀態時,java虛擬機不會給線程分配CPU,直到線程重新進入就緒狀態,它才有機會轉到運行狀態。
阻塞狀態分為三種情況:
1、 位於對象等待池中的阻塞狀態:當線程運行時,如果執行了某個對象的wait()方法,java虛擬機就回把線程放到這個對象的等待池中
2、 位於對象鎖中的阻塞狀態,當線程處於運行狀態時,試圖獲得某個對象的同步鎖時,如果該對象的同步鎖已經被其他的線程佔用,JVM就會把這個線程放到這個對象的瑣池中。
3、 其它的阻塞狀態:當前線程執行了sleep()方法,或者調用了其它線程的join()方法,或者發出了I/O請求時,就會進入這個狀態中。
Ⅷ JVM:如何分析線程堆棧
線程(thread),有時被稱為輕量級進程(Lightweight Process,LWP),是程序執行流的最小單元。一個標準的線程由線程ID,當前指令指針(PC),寄存器集合和堆棧組成。另外,線程是進程中的一個實體,是被系統獨立調度和分派的基本單位,線程自己不擁有系統資源,只擁有一點在運行中必不可少的資源,但它可與同屬一個進程的其它線程共享進程所擁有的全部資源。一個線程可以創建和撤消另一個線程,同一進程中的多個線程之間可以並發執行。由於線程之間的相互制約,致使線程在運行中呈現出間斷性。線程也有就緒、阻塞和運行三種基本狀態。
線程是程序中一個單一的順序控制流程.在單個程序中同時運行多個線程完成不同的工作,稱為多線程.
1、線程與進程
線程和進程的區別在於,子進程和父進程有不同的代碼和數據空間,而多個線程則共享數據空間,每個線程有自己的執行堆棧和程序計數器為其執行上下文.多線程主要是為了節約CPU時間,發揮利用,根據具體情況而定. 線程的運行中需要使用計算機的內存資源和CPU
通常在一個進程中可以包含若干個線程,它們可以利用進程所擁有的資源。在引入線程的操作系統中,通常都是把進程作為分配資源的基本單位,而把線程作為獨立運行和獨立調度的基本單位。由於線程比進程更小,基本上不擁有系統資源,故對它的調度所付出的開銷就會小得多,能更高效的提高系統內多個程序間並發執行的程度。
因而近年來推出的通用操作系統都引入了線程,以便進一步提高系統的並發性,並把它視為現代操作系統的一個重要指標。
Ⅸ 怎麼通過linux命令去分析jvm裡面那個線程阻塞了
仍然需要生成jvm進程的thread mp data,便於與Linux top命令輸出關聯。步驟如下:
1)執行top命令,或使用-H選項(顯示所有線程),找到相關的高CPU的PID
2)生成thread mp 快照(kill -3 PID)。
3)將top命令輸出PID轉換為HEX格式(16進制)
4)在thread mp data中搜索nid=<Hex PID>
5)分析受影響的thread和stack trace,精確定位代碼。
top output sample
[plain] view plain
PID USER PRI NI SIZE RSS SHARE STAT %CPU %MEM TIME COMMAND
...........
22111 userWLS 9 0 86616 84M 26780 S 0.0 40.1 0:00 java
Ⅹ JVM線程狀態都有哪幾種
[1]新生狀態(New):當一個線程的實例被創建即使用new關鍵字和Thread類或其子類創建一個線程對象後,此時該線程處於新生(new)狀態,處於新生狀態的線程有自己的內存空間,但該線程並沒有運行,此時線程還不是活著的(notalive)。
[2]就緒狀態(Runnable):通過調用線程實例的start()方法來啟動線程使線程進入就緒狀態(runnable);處於就緒狀態的線程已經具備了運行條件,但還沒有被分配到CPU即不一定會被立即執行,此時處於線程就緒隊列,等待系統為其分配CPCU,等待狀態並不是執行狀態;此時線程是活著的(alive)。
[3]運行狀態(Running):一旦獲取CPU(被JVM選中),線程就進入運行(running)狀態,線程的run()方法才開始被執行;在運行狀態的線程執行自己的run()方法中的操作,直到調用其他的方法而終止、或者等待某種資源而阻塞、或者完成任務而死亡;如果在給定的時間片內沒有執行結束,就會被系統給換下來回到線程的等待狀態;此時線程是活著的(alive)。
[4]阻塞狀態(Blocked):通過調用join()、sleep()、wait()或者資源被暫用使線程處於阻塞(blocked)狀態;處於Blocking狀態的線程仍然是活著的(alive)。
[5]死亡狀態(Dead):當一個線程的run()方法運行完畢或被中斷或被異常退出,該線程到達死亡(dead)狀態。此時可能仍然存在一個該Thread的實例對象,當該Thread已經不可能在被作為一個可被獨立執行的線程對待了,線程的獨立的callstack已經被dissolved。一旦某一線程進入Dead狀態,他就再也不能進入一個獨立線程的生命周期了。對於一個處於Dead狀態的線程調用start()方法,會出現一個運行期(runtimeexception)的異常;處於Dead狀態的線程不是活著的(notalive)。