使用Swing进行多线程处理

时间:2015-11-25 03:46:20

标签: java multithreading swing concurrency swingworker

我正在尝试用Swing编写一个多线程程序。本质上该程序的工作原理是,当它运行时,它将有一个机器人(在屏幕截图中用圆圈表示),它在一个字段中徘徊。这个机器人应该由它自己的线程控制。该程序有一个按钮" Launch Robot"这将在场上创造另一个机器人(最多10个)。现在我有程序的基础知识,但它都在一个线程下运行。我可以根据需要启动尽可能多的机器人,但它们都在一个线程下运行。但是每当我点击"启动Robot"创建一个独立的线程并控制该机器人。这就是该程序现在的样子: enter image description here

该程序的UML图如下: enter image description here

由于它有点长,我不会发布整个节目。但是启动和更新机器人的方法(目前仅控制场上的一个机器人)如下:

    public void gameStart(){
    Thread gameThread = new Thread(){
        public void run(){
            while(true){
                //execute one time step for the game
                gameUpdate();

                //refresh screen
                repaint();

                //give other threads time
                try{
                    Thread.sleep(1000/UPDATE_RATE);
                }catch(InterruptedException e){
                    e.printStackTrace();
                }
            }
        }
    };

    gameThread.start();
}

我的问题是如何在这种情况下实现多线程?我知道SwingWorker的基础知识,但由于我还没有完成任何多线程,我不知道如何使多个线程工作并由一个线程更新(更新控制的机器人的位置)通过线程)。

编辑:只是为了表明我的观点,这是我正在研究的项目。它不是关于多线程在这种情况下是否有意义。

3 个答案:

答案 0 :(得分:2)

创建包含RobotModel的{​​{1}}并定义其互动。在SwingWorkerCollection<Robot>实现中迭代模型。在有意义的事件发生时调用doInBackground(),并通过查询模型publish()更新process()视图。正如here所讨论的那样,模型中应该没有绘图,视图中没有交互逻辑。单个工作人员应该足够适合中等复杂的模型,但您可以按照here所示同步多个工作人员。

答案 1 :(得分:1)

实现这一目标的一个好方法是使用ScheduledThreadPoolExecutor 通过以下方式实例化线程池:

namespace RockPaperScissors
{
    enum GameAction
    {
        Rock,
        Paper,
        Scissors
    }

    abstract class Player
    {
        public abstract GameAction Act();
    }

    class PlayerRock : Player
    {
        public override GameAction Act()
        {
            return GameAction.Rock;
        }
    }

要创建新的机器人线程,请使用:

ScheduledThreadPoolExecutor threadsPool = new ScheduledThreadPoolExecutor(size);

这样,每次调用都会实例化一个新的Thread 您可以通过“size”参数设置允许线程总数的限制 您还可以在每个线程完成后使用以下内容传递结果:

    threadsPool.submit(new Runnable() {
        @Override
        public void run() {
            launchRobot();
        }
    });

如果您想要更少的细节,可以使用以下便利API让Java为您完成工作:
 public <T> Future<T> submit(Runnable task, T result) (无界线程池,具有自动线程回收)或:
Executors.newCachedThreadPool()(固定大小的线程池)

记住我们,执行官。记住今天在这里做了什么。也许Adun会监视你

答案 2 :(得分:1)

  

这个机器人应该由它自己的线程控制。

为什么?

IMO,描述任何线程的最重要方式是说明等待的内容。在Internet服务器中,接受线程等待来自新客户端的传入连接,客户端线程等待来自单个客户端的其他命令。在执行大规模并行计算的程序中,工作线程等待执行任务。在GUI程序中,事件调度线程等待键盘和鼠标事件。等等。

您的机器人线程会等待什么?

如果它等待时间过去(即,如果它调用Thread.sleep()),那么你的GUI框架可能已经有一个计时器线程这样做,你可能想要考虑使用它。 (在Swing中,您将使用javax.swing.Timer类提交新的定时任务。)