ThreadViewer.java Source code

Java tutorial

Introduction

Here is the source code for ThreadViewer.java

Source

import java.awt.BorderLayout;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.lang.reflect.InvocationTargetException;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingUtilities;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;

public class ThreadViewer extends JPanel {
    private ThreadViewerTableModel tableModel = new ThreadViewerTableModel();

    public ThreadViewer() {

        JTable table = new JTable(tableModel);
        table.setAutoResizeMode(JTable.AUTO_RESIZE_LAST_COLUMN);

        TableColumnModel colModel = table.getColumnModel();
        int numColumns = colModel.getColumnCount();

        for (int i = 0; i < numColumns - 1; i++) {
            TableColumn col = colModel.getColumn(i);

            col.sizeWidthToFit();
            col.setPreferredWidth(col.getWidth() + 5);
            col.setMaxWidth(col.getWidth() + 5);
        }

        JScrollPane sp = new JScrollPane(table);

        setLayout(new BorderLayout());
        add(sp, BorderLayout.CENTER);
    }

    public void dispose() {
        tableModel.stopRequest();
    }

    protected void finalize() throws Throwable {
        dispose();
    }

    public static void main(String[] args) {
        JFrame f = new JFrame();
        ThreadViewer viewer = new ThreadViewer();

        f.setContentPane(viewer);
        f.setSize(500, 300);
        f.setVisible(true);

        f.setDefaultCloseOperation(1);

        // Keep the main thread from exiting by blocking
        // on wait() for a notification that never comes.
        Object lock = new Object();
        synchronized (lock) {
            try {
                lock.wait();
            } catch (InterruptedException x) {
            }
        }
    }
}

class ThreadViewerTableModel extends AbstractTableModel {
    private Object dataLock;

    private int rowCount;

    private Object[][] cellData;

    private Object[][] pendingCellData;

    private final int columnCount;

    private final String[] columnName;

    private final Class[] columnClass;

    private Thread internalThread;

    private volatile boolean noStopRequested;

    public ThreadViewerTableModel() {
        rowCount = 0;
        cellData = new Object[0][0];

        String[] names = { "Priority", "Alive", "Daemon", "Interrupted", "ThreadGroup", "Thread Name" };
        columnName = names;

        Class[] classes = { Integer.class, Boolean.class, Boolean.class, Boolean.class, String.class,
                String.class };
        columnClass = classes;

        columnCount = columnName.length;

        dataLock = new Object();

        noStopRequested = true;
        Runnable r = new Runnable() {
            public void run() {
                try {
                    runWork();
                } catch (Exception x) {
                    // in case ANY exception slips through
                    x.printStackTrace();
                }
            }
        };

        internalThread = new Thread(r, "ThreadViewer");
        internalThread.setPriority(Thread.MAX_PRIORITY - 2);
        internalThread.setDaemon(true);
        internalThread.start();
    }

    private void runWork() {
        Runnable transferPending = new Runnable() {
            public void run() {
                transferPendingCellData();
                fireTableDataChanged();
            }
        };

        while (noStopRequested) {
            try {
                createPendingCellData();
                SwingUtilities.invokeAndWait(transferPending);
                Thread.sleep(5000);
            } catch (InvocationTargetException tx) {
                tx.printStackTrace();
                stopRequest();
            } catch (InterruptedException x) {
                Thread.currentThread().interrupt();
            }
        }
    }

    public void stopRequest() {
        noStopRequested = false;
        internalThread.interrupt();
    }

    public boolean isAlive() {
        return internalThread.isAlive();
    }

    private void createPendingCellData() {
        Thread[] thread = findAllThreads();
        Object[][] cell = new Object[thread.length][columnCount];

        for (int i = 0; i < thread.length; i++) {
            Thread t = thread[i];
            Object[] rowCell = cell[i];

            rowCell[0] = new Integer(t.getPriority());
            rowCell[1] = new Boolean(t.isAlive());
            rowCell[2] = new Boolean(t.isDaemon());
            rowCell[3] = new Boolean(t.isInterrupted());
            rowCell[4] = t.getThreadGroup().getName();
            rowCell[5] = t.getName();
        }

        synchronized (dataLock) {
            pendingCellData = cell;
        }
    }

    private void transferPendingCellData() {
        synchronized (dataLock) {
            cellData = pendingCellData;
            rowCount = cellData.length;
        }
    }

    public int getRowCount() {
        return rowCount;
    }

    public Object getValueAt(int row, int col) {
        return cellData[row][col];
    }

    public int getColumnCount() {
        return columnCount;
    }

    public Class getColumnClass(int columnIdx) {
        return columnClass[columnIdx];
    }

    public String getColumnName(int columnIdx) {
        return columnName[columnIdx];
    }

    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);

        Thread[] list = new Thread[actualSize];
        System.arraycopy(slackList, 0, list, 0, actualSize);

        return list;
    }
}