擷取 Java VM 中當前啟動並執行所有線程
程式運行圖:
下面的靜態方法可以用數組返回 Java VM 中當前啟動並執行所有線程
public static Thread[] findAllThreads() {
ThreadGroup group =
Thread.currentThread().getThreadGroup();
ThreadGroup topGroup = group;
// 遍曆線程組樹,擷取根線程組
while ( group != null ) {
topGroup = group;
group = group.getParent();
}
// 啟用的線程數加倍
int estimatedSize = topGroup.activeCount() * 2;
Thread[] slackList = new Thread[estimatedSize];
//擷取根線程組的所有線程
int actualSize = topGroup.enumerate(slackList);
// copy into a list that is the exact size
Thread[] list = new Thread[actualSize];
System.arraycopy(slackList, 0, list, 0, actualSize);
return list;
}
程式 ThreadViewer.java 以圖形方式顯示 Java VM 中當前啟動並執行所有線程,它每隔 2 秒自動重新整理一次,以保持獲得最新資訊。程式 ThreadViewer.java 原始碼:
package thread;<br />import java.awt.*;<br />import java.awt.event.*;<br />import javax.swing.*;<br />import javax.swing.table.*;<br />public class ThreadViewer extends JPanel {<br />private ThreadViewerTableModel tableModel;<br />public ThreadViewer() {<br />tableModel = new ThreadViewerTableModel();<br />JTable table = new JTable(tableModel);<br />table.setAutoResizeMode(JTable.AUTO_RESIZE_LAST_COLUMN);<br />TableColumnModel colModel = table.getColumnModel();<br />int numColumns = colModel.getColumnCount();<br />// manually size all but the last column<br />for ( int i = 0; i < numColumns - 1; i++ ) {<br />TableColumn col = colModel.getColumn(i);<br />col.sizeWidthToFit();<br />col.setPreferredWidth(col.getWidth() + 5);<br />col.setMaxWidth(col.getWidth() + 5);<br />}<br />JScrollPane sp = new JScrollPane(table);<br />setLayout(new BorderLayout());<br />add(sp, BorderLayout.CENTER);<br />}<br />public void dispose() {<br />tableModel.stopRequest();<br />}<br />protected void finalize() throws Throwable {<br />dispose();<br />}<br />public static JFrame createFramedInstance() {<br />final ThreadViewer viewer = new ThreadViewer();<br />final JFrame f = new JFrame("ThreadViewer");<br />f.addWindowListener(new WindowAdapter() {<br />public void windowClosing(WindowEvent e) {<br />f.setVisible(false);<br />f.dispose();<br />viewer.dispose();<br />}<br />});<br />f.setContentPane(viewer);<br />f.setSize(500, 300);<br />f.setVisible(true);<br />return f;<br />}</p><p>public static void main(String[] args) {<br />JFrame f = ThreadViewer.createFramedInstance();<br />// For this example, exit the VM when the viewer<br />// frame is closed.<br />f.addWindowListener(new WindowAdapter() {<br />public void windowClosing(WindowEvent e) {<br />System.exit(0);<br />}<br />});<br />// Keep the main thread from exiting by blocking<br />// on wait() for a notification that never comes.<br />Object lock = new Object();<br />synchronized ( lock ) {<br />try {<br />lock.wait();<br />} catch ( InterruptedException x ) {<br />}<br />}<br />}<br />}<br />
程式 ThreadViewerTableModel.java 原始碼:
package thread;<br />import java.awt.*;<br />import java.lang.reflect.*;<br />import javax.swing.*;<br />import javax.swing.table.*;<br />public class ThreadViewerTableModel extends AbstractTableModel {<br />private Object dataLock;<br />private int rowCount;<br />private Object[][] cellData;<br />private Object[][] pendingCellData;<br />// the column information remains constant<br />private final int columnCount;<br />private final String[] columnName;<br />private final Class[] columnClass;<br />// self-running object control variables<br />private Thread internalThread;<br />private volatile boolean noStopRequested;<br />public ThreadViewerTableModel() {<br />rowCount = 0;<br />cellData = new Object[0][0];<br />// JTable uses this information for the column headers<br />String[] names = {<br />"Priority", "Alive",<br />"Daemon", "Interrupted",<br />"ThreadGroup", "Thread Name" };<br />columnName = names;</p><p>// JTable uses this information for cell rendering<br />Class[] classes = {<br />Integer.class, Boolean.class,<br />Boolean.class, Boolean.class,<br />String.class, String.class };<br />columnClass = classes;<br />columnCount = columnName.length;<br />// used to control concurrent access<br />dataLock = new Object();<br />noStopRequested = true;<br />Runnable r = new Runnable() {<br />public void run() {<br />try {<br />runWork();<br />} catch ( Exception x ) {<br />// in case ANY exception slips through<br />x.printStackTrace();<br />}<br />}<br />};<br />internalThread = new Thread(r, "ThreadViewer");<br />internalThread.setPriority(Thread.MAX_PRIORITY - 2);<br />internalThread.setDaemon(true);<br />internalThread.start();<br />}<br />private void runWork() {<br />// The run() method of transferPending is called by<br />// the event handling thread for safe concurrency.<br />Runnable transferPending = new Runnable() {<br />public void run() {<br />transferPendingCellData();<br />// Method of AbstractTableModel that<br />// causes the table to be updated.<br />fireTableDataChanged();<br />}<br />};<br />while ( noStopRequested ) {<br />try {<br />createPendingCellData();<br />SwingUtilities.invokeAndWait(transferPending);<br />Thread.sleep(2000);<br />} catch ( InvocationTargetException tx ) {<br />tx.printStackTrace();<br />stopRequest();<br />} catch ( InterruptedException x ) {<br />Thread.currentThread().interrupt();<br />}<br />}<br />}<br />public void stopRequest() {<br />noStopRequested = false;<br />internalThread.interrupt();<br />}<br />public boolean isAlive() {<br />return internalThread.isAlive();<br />}<br />private void createPendingCellData() {<br />// this method is called by the internal thread<br />Thread[] thread = findAllThreads();<br />Object[][] cell = new Object[thread.length][columnCount];<br />for ( int i = 0; i < thread.length; i++ ) {<br />Thread t = thread[i];<br />Object[] rowCell = cell[i];<br />rowCell[0] = new Integer(t.getPriority());<br />rowCell[1] = new Boolean(t.isAlive());<br />rowCell[2] = new Boolean(t.isDaemon());<br />rowCell[3] = new Boolean(t.isInterrupted());<br />rowCell[4] = t.getThreadGroup().getName();<br />rowCell[5] = t.getName();<br />}<br />synchronized ( dataLock ) {<br />pendingCellData = cell;<br />}<br />}<br />private void transferPendingCellData() {<br />// this method is called by the event thread<br />synchronized ( dataLock ) {<br />cellData = pendingCellData;<br />rowCount = cellData.length;<br />}<br />}<br />public int getRowCount() {<br />// this method is called by the event thread<br />return rowCount;<br />}</p><p>public Object getValueAt(int row, int col) {<br />// this method is called by the event thread<br />return cellData[row][col];<br />}<br />public int getColumnCount() {<br />return columnCount;<br />}<br />public Class getColumnClass(int columnIdx) {<br />return columnClass[columnIdx];<br />}<br />public String getColumnName(int columnIdx) {<br />return columnName[columnIdx];<br />}<br />public static Thread[] findAllThreads() {<br />ThreadGroup group =<br />Thread.currentThread().getThreadGroup();<br />ThreadGroup topGroup = group;<br />// traverse the ThreadGroup tree to the top<br />while ( group != null ) {<br />topGroup = group;<br />group = group.getParent();<br />}<br />// Create a destination array that is about<br />// twice as big as needed to be very confident<br />// that none are clipped.<br />int estimatedSize = topGroup.activeCount() * 2;<br />Thread[] slackList = new Thread[estimatedSize];<br />// Load the thread references into the oversized<br />// array. The actual number of threads loaded<br />// is returned.<br />int actualSize = topGroup.enumerate(slackList);<br />// copy into a list that is the exact size<br />Thread[] list = new Thread[actualSize];<br />System.arraycopy(slackList, 0, list, 0, actualSize);<br />return list;<br />}<br />}<br />
原文連結:http://www.java3z.com/cwbwebhome/article/article5a/5138.html?id=266