我有一个要运行的蒙特卡洛模拟,并不断更新系统当前状态的可视化。我有一个提供方法IsingModel的类Iterator<IsingModel> metropolisIterator。在迭代器上调用next()将运行一个模拟周期,从而更新系统状态。系统取决于温度变量IsingModel.temperature,可以在迭代之间进行更改。

例如

int t1 = 1;
int t2 = 2;

IsingModel model = new IsingModel(t1);
Iterator<IsingModel> mItr = model.metropolisIterator();
mItr.next() // simulation undergoes one iteration with t=t1
model.setTemperature(t2);
mItr.next() // simulation undergoes one iteration with t=t2


为了可视化我的模拟

public class IsingModelWindow extends JFrame
{
    public class SpinPanel extends JPanel
    {
        public void setModel(IsingModel model)
        {
            // some code to create a visualisation
        }

        @Override
        public void paintComponent(Graphics g)
        {
             // paint the visualisation
        }
    }

    public class TemperatureSlider extends JSlider
    {
         // some stuff
    }

    private class IsingModelTask extends SwingWorker<Void, IsingModel>
    {
        private IsingModel model;
        private Iterator<IsingModel> mItr;

        public IsingModelTask(int temp)
        {
            model = new IsingModel(temp);
            mItr = model.metropolisIterator();
        }
        @Override
        protected Void doInBackground()
        {
            while(!isCancelled())
            {
                publish(model);
                mItr.next();
            }
            return null;
        }
        @Override
        protected void process(List<IsingModel> models)
        {
            IsingModel model = models.get(models.size() - 1);
            spinPanel.setModel(model);
        }
    }

    private SpinPanel spinPanel;
    private TemperatureSlider temperatureSlider;
    private IsingModelTask task;

    public IsingModelWindow()
    {
        spinPanel = new SpinPanel();
        temperatureSlider = new TemperatureSlider();
        task = new IsingModelTask(temperatureSlider.getValue());
        task.execute();
    }
}


现在,我想做的就是能够在更改IsingModelTask.model时以新的温度更新temperatureSlider,但是我相信这会引起一些线程问题。用ChangeListener进行此操作的最佳方法是什么?

最佳答案

无论如何,您可能都会遇到线程问题:将模型传递给事件分发线程上的SpinPanel。据我所知,该模型只有一个实例。这意味着在事件调度线程创建可视化文件(即执行setModel中的代码)时,工作线程可能已经继续修改模型。

关于最棘手的问题:无论如何,您都需要ChangeListener对更改做出反应。问题是:ChangeListener对新的滑块值有何作用?根据您的描述,这不能传递给EDT上的模型,因为更改可能会干扰当前在后台工作线程上更新的模型。务实的解决方案是将新的,更新的值从滑块直接传递到IsingModelTask,然后通过doInBackground方法将其传递到模型。

关于java - 与正在运行的SwingWorker进行通信,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/21606851/

10-11 02:26