【问题标题】:Modify variable in EDT修改 EDT 中的变量
【发布时间】:2017-11-03 09:10:38
【问题描述】:

当我设置数字[0] = 10 时,我的循环没有停止,当按下 jbutton 时,while 循环的线程看不到正在更改的数字,我该如何解决这个问题?我相信线程被阻塞了。

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

}

【问题讨论】:

  • 对共享变量(本例中为数字)的访问应该是同步的。
  • 或使用 AtomicInteger 代替数组
  • 同步函数?
  • 不是带有循环的整个函数;只有对数字的访问。或者创建一个 getNumber 和 setNumber 并将它们声明为同步。不过使用 AtomicInteger 会更简单、更快。
  • 明白了!我试试看

标签: java multithreading user-interface awt edt


【解决方案1】:

我希望这只是一些线程练习。要跨线程共享值,您需要确保访问正确同步,虽然有多种方法可以做到这一点,但最简单的方法之一可能是使用 AtomicInteger 来处理所有多线程访问为您提供的功能。

我还包含了一个简单的“锁定”类,这意味着Thread 不会“放任自流”失控,并为 UI 提供一种方法来提醒线程发生了变化,其中然后它可以处理该值。

所有这些都在线程监视器和 UI 类之间共享。

我强烈建议您查看Concurrency Trail,它更详细地介绍了此信息

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

该示例将以2 为步长增加值(从0),让您看到线程处理它直到达到10

如果您愿意,您可以创建一个包含 CommonLockAtomicInteger 的单个类,使管理稍微容易一些,但我会留给您处理

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-01-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-01-02
    • 2015-11-11
    • 2011-04-09
    相关资源
    最近更新 更多