import java.awt.*; import java.awt.event.*; import javax.swing.*; public class SyncRaceGUI3 extends JFrame implements ActionListener { private JTextField numField, counterField, statusField; private JButton start, stop; private Counter c; private CountThread c1, c2; public SyncRaceGUI3() { setTitle("Race Condition"); setSize(500, 100); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); Container pane = getContentPane(); pane.setLayout(new FlowLayout()); numField = new JTextField(10); pane.add(numField); start = new JButton("Start Counters"); start.addActionListener(this); pane.add(start); stop = new JButton("Stop"); stop.addActionListener(this); pane.add(stop); statusField = new JTextField(10); pane.add(statusField); counterField = new JTextField(20); pane.add(counterField); c = new Counter(); c1 = c2 = null; } public void actionPerformed(ActionEvent e) { if (e.getSource() == start && c1 == null && c2 == null) { int n = Integer.parseInt(numField.getText()); c1 = new CountThread(c, 1, n); c2 = new CountThread(c, -1, n); c1.start(); c2.start(); statusField.setText("running..."); } else if (e.getSource() == stop) { if (c1 != null) {c1.interrupt();} if (c2 != null) {c2.interrupt();} } } public void done(CountThread d) { if (d == c1) {c1 = null;} else {c2 = null;} if (c1 == null && c2 == null) { statusField.setText("Finished"); } } class Counter { private long x = 0; public long getX() {return x;} public void increaseX(long incr) {x = x + incr;} public String toString() {return "Count: " + x;} } class CountThread extends Thread { private long incr, total; private Counter counter; public CountThread(Counter c, long i, long n) { counter = c; incr = i; total = n; } public void run() { for (long i = 0; !isInterrupted() && i < total; ++i) { synchronized(counter) { counter.increaseX(incr); counterField.setText(counter.toString()); } } done(this); } } public static void main(String[] args) { SyncRaceGUI3 f = new SyncRaceGUI3(); f.setVisible(true); } }