Modify variable in EDT

53 Views Asked by At

My loop is not stopping when i set the number[0] = ten, the thread for the while loop can't see the number being changed when the jbutton is pressed, How do i fixed this? I believe the thread is being blocked.

    public class A{

        private int[] number = new number[1];
        private number_game gui;


        public A(){
        }

        public void thread_loop(){

            gui = new number_game();
            gui.the_game(number);

            Thread nums = new Thread(){

                public void run(){

                    while(number[0]!= 10){

                           if(number != 10)
                              System.out.println("wrong number")
                    }

                };nums.start();

            } 
        }

    }

public class number_game extends Jframe{

......

    public number_game(){}

    / creating gui
    public void the_game(int [] guess){

       .............
       checkguess.addActionListener(new ActionListener() {
           @Override
           public void actionPerformed(ActionEvent e){

                  guess[1] = 10;
                  dispose();

            }
        });
   }
}

public class main{
    public static void main(String[]args) {

    A nums_play = new A();
    nums_play.thread_loop();
    }

}
1

There are 1 best solutions below

0
On

I'm hoping that this is just some threading practice. To share values across threads you need to make sure that the access is synchronized properly, while there are a number of ways to do it, one of the simplest might be to use a AtomicInteger which takes care of all the multi-thread access functionality for you.

I've also included a simple "lock" class which means that the Thread doesn't "free wheel" out of control and provides a means for the UI to alert the thread that a change has occurred, to which it can then process the value.

All this is shared across the thread monitor and UI classes.

I strongly recommend having a look at the Concurrency Trail which covers this information in more detail

import java.awt.HeadlessException;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

public class Test extends JFrame {

    public static void main(String[] args) {
        new Test();
    }

    public class CommonLock {

        private ReentrantLock lock;
        private Condition condition;

        public CommonLock() {
            lock = new ReentrantLock();
            condition = lock.newCondition();
        }

        protected void lock() {
            lock.lock();
        }

        protected void unlock() {
            lock.unlock();
        }

        public void await() throws InterruptedException {
            lock();
            try {
                condition.await();
            } finally {
                unlock();
            }
        }

        public void signal() {
            lock();
            try {
                condition.signal();
            } finally {
                unlock();
            }
        }

    }

    public Test() throws HeadlessException {
        CommonLock lock = new CommonLock();
        AtomicInteger value = new AtomicInteger(0);
        ThreadMonitor monitor = new ThreadMonitor(value, lock);
        monitor.start();

        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                JFrame frame = new JFrame();
                frame.add(new TestPane(value, lock));
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        private final AtomicInteger value;
        private final CommonLock lock;

        public TestPane(AtomicInteger value, CommonLock lock) {
            this.value = value;
            this.lock = lock;
            JButton btn = new JButton("Pick");
            btn.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    value.addAndGet(2);
                    lock.signal();
                }
            });
            add(btn);
        }

    }

    public class ThreadMonitor {

        private final AtomicInteger value;
        private final CommonLock lock;

        public ThreadMonitor(AtomicInteger value, CommonLock lock) {
            this.value = value;
            this.lock = lock;
        }

        public void start() {
            Thread thread = new Thread(new Runnable() {
                @Override
                public void run() {
                    while (true) {
                        try {
                            lock.await();
                        } catch (InterruptedException ex) {
                        }
                        int number = value.get();
                        if (number == 10) {
                            break;
                        } else {
                            System.out.println("Bad Guess");
                        }
                    }
                    System.out.println("Good guess");
                }
            });
            thread.start();
        }
    }
}

The example will increment the value (from 0) in steps of 2, allow you to see the thread processing it until it reaches 10

If you wanted to, you could create a single class which emcampasses the CommonLock and AtomicInteger, making the management slightly easier, but I'll leave that up to you