Mega Code Archive

 
Categories / Java / Threads
 

Thread accuracy

import java.awt.BorderLayout; import java.awt.Color; import java.awt.Font; import java.awt.Graphics; import java.awt.GridLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.text.DecimalFormat; import javax.swing.JButton; import javax.swing.JComponent; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.border.EmptyBorder; public class SecondCounterMain extends JPanel {   private SecondCounter sc = new SecondCounter();   private JButton startB = new JButton("Start");   private JButton stopB = new JButton("Stop");   public SecondCounterMain() {     stopB.setEnabled(false);      startB.addActionListener(new ActionListener() {       public void actionPerformed(ActionEvent e) {         startB.setEnabled(false);         Thread counterThread = new Thread(sc, "Counter");         counterThread.start();         stopB.setEnabled(true);         stopB.requestFocus();       }     });     stopB.addActionListener(new ActionListener() {       public void actionPerformed(ActionEvent e) {         stopB.setEnabled(false);         sc.stopClock();         startB.setEnabled(true);         startB.requestFocus();       }     });     JPanel innerButtonP = new JPanel();     innerButtonP.setLayout(new GridLayout(0, 1, 0, 3));     innerButtonP.add(startB);     innerButtonP.add(stopB);     JPanel buttonP = new JPanel();     buttonP.setLayout(new BorderLayout());     buttonP.add(innerButtonP, BorderLayout.NORTH);     this.setLayout(new BorderLayout(10, 10));     this.setBorder(new EmptyBorder(20, 20, 20, 20));     this.add(buttonP, BorderLayout.WEST);     this.add(sc, BorderLayout.CENTER);   }   public static void main(String[] args) {     SecondCounterMain scm = new SecondCounterMain();     JFrame f = new JFrame("Second Counter");     f.setContentPane(scm);     f.setSize(320, 200);     f.setVisible(true);     f.addWindowListener(new WindowAdapter() {       public void windowClosing(WindowEvent e) {         System.exit(0);       }     });   }   class SecondCounter extends JComponent implements Runnable {     private volatile boolean keepRunning;     private Font paintFont = new Font("SansSerif", Font.BOLD, 14);     private volatile String timeMsg = "never started";     private volatile int arcLen = 0;     public SecondCounter() {     }     public void run() {       runClock();     }     public void runClock() {       DecimalFormat fmt = new DecimalFormat("0.000");       long normalSleepTime = 100;       long nextSleepTime = normalSleepTime;       int counter = 0;       long startTime = System.currentTimeMillis();       keepRunning = true;       while (keepRunning) {         try {           Thread.sleep(nextSleepTime);         } catch (InterruptedException x) {           // ignore         }         counter++;         double counterSecs = counter / 10.0;         double elapsedSecs = (System.currentTimeMillis() - startTime) / 1000.0;         double diffSecs = counterSecs - elapsedSecs;         nextSleepTime = normalSleepTime + ((long) (diffSecs * 1000.0));         if (nextSleepTime < 0) {           nextSleepTime = 0;         }         timeMsg = fmt.format(counterSecs) + " - "             + fmt.format(elapsedSecs) + " = "             + fmt.format(diffSecs);         arcLen = (((int) counterSecs) % 60) * 360 / 60;         repaint();       }     }     public void stopClock() {       keepRunning = false;     }     public void paint(Graphics g) {       g.setColor(Color.black);       g.setFont(paintFont);       g.drawString(timeMsg, 0, 15);       g.fillOval(0, 20, 100, 100); // black border       g.setColor(Color.white);       g.fillOval(3, 23, 94, 94); // white for unused portion       g.setColor(Color.blue); // blue for used portion       g.fillArc(2, 22, 96, 96, 90, -arcLen);     }   } }