Package y3.threadViz

Source Code of y3.threadViz.ThreadViz

package y3.threadViz;


import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;

import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.JToggleButton;
import javax.swing.SwingUtilities;
import javax.swing.border.EtchedBorder;



/**
* ThreadViz - abiklass, millega on mugav visualiseerida lõimede tööd
* Kuvab kõrvuti lõimede poole saadetud sõnumid
*
* Kasutamine:
*    lõime lisamine  -  ThreadViz.addThread(t) - argumendina tuleb kaasa anda viit lõimele
*    sõnumi lisamine -  ThreadViz.addMessage(msg) - kui kutsuda vastava lõime seest välja, lisab teate
*    UI kuvamine     -  ThreadViz.showUI()
*
* Kasutamise näide - vt. lõpus, klass Ticker
*
* @author Rain Öpik
*/


public class ThreadViz extends JFrame{
  private static final long serialVersionUID = 5100506006872338637L;
 
  private static int width = 1224;
  private static int height = 568;
 
  private static int MAX_MESSAGES_PER_PANEL = 500;
 
  private ButtonPanel buttonPanel;
  private JPanel vizPanel;
 
  private boolean frozen = false;
 

  private AtomicInteger msgCounter = new AtomicInteger();
 
 
  private class ButtonPanel extends JPanel {
    private static final long serialVersionUID = -2897648905282402562L;
    private JToggleButton freeze = new JToggleButton("Freeze");
    public ButtonPanel() {
      setLayout(new FlowLayout());
     
      freeze.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent arg0) {
          processMsgQueue();
          frozen = !frozen;
        }
       
      });
     
      add(freeze);
    }
  }
 
  private void processMsgQueue() {
    System.out.println("Proces");
    if (messages != null) {
      for (Thread t : messages.keySet()) {
        if (t != null) {
          ArrayList<String> msgs = messages.get(t);
         
          if (msgs != null && msgs.size() > 0) {
            displayThreadMessages(t, msgs);       
          }
        }
      }
    }
  }

  private class ThreadPanel extends JPanel {
    private static final long serialVersionUID = 5087703384652035716L;
   
    private JTextField tName = new JTextField();
    private JTextArea tMessages = new JTextArea();
   
    private AtomicInteger panelMsgCounter = new AtomicInteger();
   
    public ThreadPanel(String name) {
      setSize(200, 430);
      setPreferredSize(getSize());
      setBackground(Color.DARK_GRAY);
     
      setBorder(BorderFactory.createEtchedBorder(EtchedBorder.LOWERED));
       
      setLayout(null);
     
      int margin = 5;
      tName.setText(name);
     
      tName.setSize(getWidth() - 2*margin, 20);
      tName.setPreferredSize(tName.getSize());
      tName.setLocation(margin, margin);
      add(tName);
     
     
      JScrollPane tScroll = new JScrollPane(tMessages);
   
      tMessages.setLineWrap(true);
      tMessages.setWrapStyleWord(true);
      tMessages.setFont( new Font("Arial", Font.PLAIN, 16));
     
      tScroll.setSize(getWidth() - 2*margin, getHeight() - 2*margin - tName.getHeight());
      tScroll.setPreferredSize(tName.getSize());
      tScroll.setLocation(margin, tName.getHeight() + margin);
     
      add(tScroll)
    }
   
    public void addMessage(String msg) {
      if (panelMsgCounter.getAndIncrement() > MAX_MESSAGES_PER_PANEL) {
        tMessages.setText("// flushed log //");
        panelMsgCounter.set(0);
      }
     
      tMessages.append(msg);
    }
  }
 
  private static class Starter {
    private static String getTitle(Object o) {
      return o.getClass().getSimpleName();
    }
   
    public static void run(final JFrame frame, int width, int height) {
      frame.setTitle(getTitle(frame));
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.setSize(width, height);
      frame.setVisible(true);
    }
  }
 

  private Map<Thread, ThreadPanel> threads = new HashMap<Thread, ThreadPanel>();
  private Map<Thread, ArrayList<String>> messages = new HashMap<Thread, ArrayList<String>>();
  private static ThreadViz visualizer = new ThreadViz();
  private boolean ui = false;
  private final Object lock = new Object();
  private final Object msgLock = new Object();
 
  private void add(final Thread t) {

    synchronized(msgLock) {
      messages.put(t, new ArrayList<String>());
    }   
   
    SwingUtilities.invokeLater(new Runnable() {
      public void run() {
       
        synchronized(lock) {
          ThreadPanel tpl = new ThreadPanel(t.getName());
          threads.put(t, tpl);
         
          Container c = vizPanel;
          c.add(tpl);
         
          if (ui) {
            c.repaint();
            c.validate();
          }
        }
      }
    });
  }

 
  private void addThreadMessage(final Thread t, final String message) {
    int nextMsgNumber = msgCounter.getAndIncrement();
    String msg = "[" + nextMsgNumber + "] " + message;
    System.out.println(t.getName() + " " + msg);
       
    ArrayList<String> msgs;
   
    synchronized(msgLock) {
      msgs = messages.get(t);
    }
   
    if (msgs == null) {
      add(t);
      synchronized(msgLock) {
        msgs = messages.get(t);
      }     
    }
   
    if (msgs != null) {
      synchronized (msgs) {
        msgs.add(msg);
      }
      if (!frozen) {
        displayThreadMessages(t, msgs);
      }
    }
   
  }
 

  private void displayThreadMessages(final Thread t, ArrayList<String> msgs) {
    if (msgs == null) {
      synchronized (msgLock) {
        msgs = messages.get(t)
      }
    }
    if (msgs == null) { return; }
   
    final ArrayList<String> umsgs = msgs;
   
    SwingUtilities.invokeLater( new Runnable() {
      public void run() {
        ThreadPanel tpl = threads.get(t);
       
        if (tpl != null) {
          synchronized(umsgs) {
            Iterator<String> i = umsgs.iterator();
            while (i.hasNext()) {
              String umsg = i.next();
              i.remove();
              tpl.addMessage(umsg + "\n");
            }
          }
        }
       
      }
    });
  }
 
  private ThreadViz() {
    Container c = getContentPane();
    c.setLayout(new BorderLayout());
   
    buttonPanel = new ButtonPanel();
    vizPanel = new JPanel();
    c.add(buttonPanel, BorderLayout.PAGE_START);
    c.add(vizPanel, BorderLayout.CENTER);
  }
 
  /**
   * Kuvab lõimevaatleja kasutajaliidese
   * NB! Akna sulgemisel lõpetatakse programmi töö
   */
  public static void showUI() {
    visualizer.ui = true;
    Starter.run(visualizer, width, height);
  }
 
 
  /**
   * Lisab lõime vaatlejasse
   * @param t - viit lisatavale lõimele, lõime klassi sees olles sobib:
   */
  public static void addThread(Thread t) {
    visualizer.add(t);
  }
 
  /**
   * Lisab uue teate. Seostatakse lõimega, kes meetodi välja kutsub (Thread.currentThread())
   * NB! Vastav lõim tuleb enne teate saatmist registreerida meetodi addThread() abil
   * Teade kuvatakse vastava lõime aknas + konsoolil
   * @param msg - lisatav teade
   */
  public static void addMessage(String msg) {
    addMessage(Thread.currentThread(), msg);
  }
 
  /**
   * Lisab uue teate, võimaldab määrata lõime, kellelt teade tuli
   * @param t - teadet saatev lõim (peab olema eelnevalt registreeritud läbi meetodi addThread()
   * @param msg - lisatav teade
   */ 
  public static void addMessage(Thread t, String msg) {
    visualizer.addThreadMessage(t, msg);
  }
 
 
}





/*
* Kasutamise näide
*/

class Ticker extends Thread {
   
  int pause;
   
  public Ticker(ThreadViz v, int pause) {
    this.pause = pause;
   
    ThreadViz.addThread(this);
  }
  public void run() {
    try {
      DateFormat df = new SimpleDateFormat("hh:mm:ss");
     
      while(true) {
        sleep(pause);
       
        String teade = "Kell on:" + df.format(new java.util.Date());
        ThreadViz.addMessage(teade);
      }
     
    }catch (InterruptedException e) {}
  }
}
TOP

Related Classes of y3.threadViz.ThreadViz

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.