มีวิธีใดบ้างที่ฉันสามารถรับรายการเธรดที่กำลังรันทั้งหมดใน JVM ปัจจุบัน (รวมถึงเธรดที่ไม่ได้เริ่มโดยคลาสของฉัน)?
มันเป็นไปได้ที่จะได้รับThread
และClass
วัตถุของกระทู้ทั้งหมดในรายการหรือไม่
ฉันต้องการที่จะสามารถทำสิ่งนี้ผ่านรหัส
มีวิธีใดบ้างที่ฉันสามารถรับรายการเธรดที่กำลังรันทั้งหมดใน JVM ปัจจุบัน (รวมถึงเธรดที่ไม่ได้เริ่มโดยคลาสของฉัน)?
มันเป็นไปได้ที่จะได้รับThread
และClass
วัตถุของกระทู้ทั้งหมดในรายการหรือไม่
ฉันต้องการที่จะสามารถทำสิ่งนี้ผ่านรหัส
คำตอบ:
ในการรับชุด iterable:
Set<Thread> threadSet = Thread.getAllStackTraces().keySet();
จัดการกับรูThreadGroup
ทแบบนี้:
ThreadGroup rootGroup = Thread.currentThread().getThreadGroup();
ThreadGroup parentGroup;
while ((parentGroup = rootGroup.getParent()) != null) {
rootGroup = parentGroup;
}
ตอนนี้เรียกใช้enumerate()
ฟังก์ชันในกลุ่มรากซ้ำ ๆ อาร์กิวเมนต์ที่สองช่วยให้คุณได้รับกระทู้ทั้งหมดซ้ำ:
Thread[] threads = new Thread[rootGroup.activeCount()];
while (rootGroup.enumerate(threads, true ) == threads.length) {
threads = new Thread[threads.length * 2];
}
สังเกตวิธีที่เราเรียกแจกแจง () ซ้ำ ๆ จนกระทั่งอาร์เรย์มีขนาดใหญ่พอที่จะมีรายการทั้งหมด
rootGroup
อาจเป็นศูนย์และถ้าเป็นคุณจะพบกับการวนซ้ำไม่สิ้นสุด new Thread[rootGroup.activeCount()+1]
activeCount()
ใช่จะดูที่ได้รับรายชื่อของกระทู้ ตัวอย่างจำนวนมากในหน้านั้น
นั่นคือการทำโปรแกรม หากคุณต้องการรายการบน Linux อย่างน้อยคุณก็สามารถใช้คำสั่งนี้:
kill -3 processid
และ VM จะทำการเธรดดัมพ์ไปยัง stdout
คุณจะได้รับข้อมูลจำนวนมากเกี่ยวกับกระทู้จากThreadMXBean
เรียกใช้เมธอดManagementFactory.getThreadMXBean ()แบบคงที่เพื่อรับการอ้างอิงถึง MBean
คุณลองดูที่jconsoleบ้างไหม?
นี่จะแสดงรายการเธรดทั้งหมดที่ทำงานสำหรับกระบวนการ Java เฉพาะ
คุณสามารถเริ่ม jconsole จากโฟลเดอร์ JDK bin
คุณยังสามารถรับการติดตามแบบเต็มสแต็กสำหรับเธรดทั้งหมดโดยกดปุ่มCtrl+Break
ใน Windows หรือโดยการส่งkill pid --QUIT
ใน Linux
ผู้ใช้ Apache Commons สามารถใช้งานThreadUtils
ได้ การนำไปใช้ในปัจจุบันใช้วิธีการเดินตามกลุ่มเธรดที่อธิบายไว้ก่อนหน้านี้
for (Thread t : ThreadUtils.getAllThreads()) {
System.out.println(t.getName() + ", " + t.isDaemon());
}
คุณสามารถลองสิ่งนี้:
Thread.getAllStackTraces().keySet().forEach((t) -> System.out.println(t.getName() + "\nIs Daemon " + t.isDaemon() + "\nIs Alive " + t.isAlive()));
และแน่นอนคุณสามารถรับลักษณะเธรดเพิ่มเติมถ้าคุณต้องการ
ในGroovyคุณสามารถเรียกวิธีการส่วนตัวได้
// Get a snapshot of the list of all threads
Thread[] threads = Thread.getThreads()
ในJavaคุณสามารถเรียกใช้เมธอดดังกล่าวโดยใช้การสะท้อนหากผู้จัดการความปลอดภัยอนุญาต
ข้อมูลโค้ดเพื่อรับรายการเธรดที่เริ่มโดยเธรดหลัก:
import java.util.Set;
public class ThreadSet {
public static void main(String args[]) throws Exception{
Thread.currentThread().setName("ThreadSet");
for ( int i=0; i< 3; i++){
Thread t = new Thread(new MyThread());
t.setName("MyThread:"+i);
t.start();
}
Set<Thread> threadSet = Thread.getAllStackTraces().keySet();
for ( Thread t : threadSet){
if ( t.getThreadGroup() == Thread.currentThread().getThreadGroup()){
System.out.println("Thread :"+t+":"+"state:"+t.getState());
}
}
}
}
class MyThread implements Runnable{
public void run(){
try{
Thread.sleep(5000);
}catch(Exception err){
err.printStackTrace();
}
}
}
เอาท์พุท:
Thread :Thread[MyThread:2,5,main]:state:TIMED_WAITING
Thread :Thread[MyThread:0,5,main]:state:TIMED_WAITING
Thread :Thread[MyThread:1,5,main]:state:TIMED_WAITING
Thread :Thread[ThreadSet,5,main]:state:RUNNABLE
หากคุณต้องการกระทู้ทั้งหมดรวมถึงกระทู้ระบบซึ่งโปรแกรมของคุณยังไม่ได้เริ่มให้ลบเงื่อนไขด้านล่าง
if ( t.getThreadGroup() == Thread.currentThread().getThreadGroup())
ตอนนี้ออก:
Thread :Thread[MyThread:2,5,main]:state:TIMED_WAITING
Thread :Thread[Reference Handler,10,system]:state:WAITING
Thread :Thread[MyThread:1,5,main]:state:TIMED_WAITING
Thread :Thread[ThreadSet,5,main]:state:RUNNABLE
Thread :Thread[MyThread:0,5,main]:state:TIMED_WAITING
Thread :Thread[Finalizer,8,system]:state:WAITING
Thread :Thread[Signal Dispatcher,9,system]:state:RUNNABLE
Thread :Thread[Attach Listener,5,system]:state:RUNNABLE
public static void main(String[] args) {
// Walk up all the way to the root thread group
ThreadGroup rootGroup = Thread.currentThread().getThreadGroup();
ThreadGroup parent;
while ((parent = rootGroup.getParent()) != null) {
rootGroup = parent;
}
listThreads(rootGroup, "");
}
// List all threads and recursively list all subgroup
public static void listThreads(ThreadGroup group, String indent) {
System.out.println(indent + "Group[" + group.getName() +
":" + group.getClass()+"]");
int nt = group.activeCount();
Thread[] threads = new Thread[nt*2 + 10]; //nt is not accurate
nt = group.enumerate(threads, false);
// List every thread in the group
for (int i=0; i<nt; i++) {
Thread t = threads[i];
System.out.println(indent + " Thread[" + t.getName()
+ ":" + t.getClass() + "]");
}
// Recursively list all subgroups
int ng = group.activeGroupCount();
ThreadGroup[] groups = new ThreadGroup[ng*2 + 10];
ng = group.enumerate(groups, false);
for (int i=0; i<ng; i++) {
listThreads(groups[i], indent + " ");
}
}
ในคอนโซล Java, กดCtrl-หยุด มันจะแสดงรายการกระทู้ทั้งหมดรวมถึงข้อมูลบางอย่างเกี่ยวกับกอง สิ่งนี้จะไม่ทำให้คุณสามารถเข้าถึงวัตถุได้แน่นอน แต่มันจะมีประโยชน์มากสำหรับการแก้ไขข้อบกพร่องต่อไป
ในการรับรายการเธรดและสถานะเต็มโดยใช้เทอร์มินัลคุณสามารถใช้คำสั่งด้านล่าง:
jstack -l <PID>
PID ใดเป็นรหัสของกระบวนการที่ทำงานบนคอมพิวเตอร์ของคุณ เพื่อรับรหัสกระบวนการของกระบวนการ Java ของคุณคุณสามารถเรียกใช้jps
คำสั่ง
นอกจากนี้คุณยังสามารถวิเคราะห์การถ่ายโอนข้อมูลหัวข้อของคุณที่ผลิตโดย jstack ใน TDAs (การถ่ายโอนข้อมูลกระทู้วิเคราะห์) เช่นfastthreadหรือเครื่องมือวิเคราะห์ด้าย Spotify