有没有一种在主代码继续之前关闭线程的快速方法?

时间:2019-05-31 20:28:48

标签: java multithreading join

我有一个学生在学校进行西蒙游戏以完成最后的项目,我整天都在努力解决她的问题。 她正在尝试创建游戏Simon。该程序随机选择一系列颜色,并通过将4个彩色按钮的颜色从常规颜色更改为白色几秒钟然后再返回来突出显示这些颜色。 编程不是一次突出显示一种颜色,而是使所有颜色同时显示为白色。因此用户不知道顺序。

我一直在寻找运行多个线程的问题,并尝试使用.join()函数。但是,使用这种颜色时,颜色不会变成白色。

//突出显示数组中当前的颜色


public void play() {

   //loop through the array and look at all the colours so far     
   for(int i=0; i<round;i++){

             //red is the position in the array
             if(colours[i]==1){

                  Thread sleep=new Thread(new Runnable(){
                     @Override
                     public void run(){
                         //change the colour of the red button to white
                         redButton.setBackground(Color.WHITE);
                         redButton.setOpaque(true);


                            //wait 
                            try {
                                Thread.currentThread().sleep(1000);
                                }
                             catch (InterruptedException e) {
                                e.printStackTrace();
                                }
                            //change the colour back
                        redButton.setBackground(Color.RED);
                         redButton.setOpaque(false);
                     }
                 });

                        sleep.start();


             }




             //yellow
             else if(colours[i]==2){
                 Thread sleep=new Thread(new Runnable(){
                     @Override
                     public void run(){
                         yellowButton.setBackground(Color.WHITE);
                         yellowButton.setOpaque(true);


                            try {
                                Thread.currentThread().sleep(1000);
                                }
                             catch (InterruptedException e) {
                                e.printStackTrace();
                                }
                         yellowButton.setBackground(Color.YELLOW); 
                        yellowButton.setOpaque(false);
                     }
                 });
                 sleep.start();




             }
             //green
             else if(colours[i]==3){
                 Thread sleep=new Thread(new Runnable(){
                     @Override
                     public void run(){
                         greenButton.setBackground(Color.WHITE);
                         greenButton.setOpaque(true);


                            try {
                                Thread.currentThread().sleep(1000);
                                }
                             catch (InterruptedException e) {
                                e.printStackTrace();
                                }
                         greenButton.setBackground(Color.GREEN); 
                        greenButton.setOpaque(false);


                     }
                 });
                 sleep.start();



             }
             //blue
             else if(colours[i]==4){
                 Thread sleep=new Thread(new Runnable(){
                     @Override
                     public void run(){
                         blueButton.setBackground(Color.WHITE);
                         blueButton.setOpaque(true);


                            try {
                                Thread.currentThread().sleep(1000);
                                }
                             catch (InterruptedException e) {
                                e.printStackTrace();
                                }
                         blueButton.setBackground(Color.CYAN); 
                         blueButton.setOpaque(false);


                     }
                 });
                 sleep.start();




             }  

   }

}

2 个答案:

答案 0 :(得分:0)

那里的代码基本上说。

对于序列中的所有步骤,每个都启动一个线程。
然后将这些线程中的每个线程(所有线程彼此之间都很快启动,而不是在前一个线程完成之前启动。)将背景设置为白色1秒钟,然后返回。

通常,您希望在后台更新ui,以便您可以继续进行交互,但是在这种情况下,您正在播放序列,不需要任何输入。如果需要在后台进行更新,则将整个循环放在一个线程中,您将希望在该循环的迭代之间休眠。否则,只需在主线程中执行即可。为用户播放完该序列后,它将控制权传递回事件循环以等待按下。

延迟也应为.3s

答案 1 :(得分:0)

虽然您想将每个按钮的颜色更改1秒钟,但您的主线程太快,无法在该秒钟内完成。这就是为什么似乎所有灯都同时改变的原因。

一个简单的解决方案是使外线程休眠一段时间,但这不会保证线程的顺序。我建议使用java.util.concurrent.CountDownLatch来使外线程等待内线程完成。

    for (int i = 0; i < round; i++) {
        CountDownLatch countDownLatch = new CountDownLatch(1);
        // red is the position in the array
        if (colours[i] == 1) {
            Thread sleep = new Thread(new Worker(redButton, Color.RED, countDownLatch))
            sleep.start();

        }

        // yellow
        else if (colours[i] == 2) {
            Thread sleep = new Thread(new Worker(yellowButton, Color.YELLOW, countDownLatch))
            sleep.start();

        }
        // green
        else if (colours[i] == 3) {
            Thread sleep = new Thread(new Worker(greenButton, Color.GREEN, countDownLatch))
            sleep.start();

        }
        // blue
        else if (colours[i] == 4) {
            Thread sleep = new Thread(new Worker(blueButton, Color.CYAN, countDownLatch))
            sleep.start();

        }
        countDownLatch.await();
    }
}

class Worker implements Runnable {
    Button button;
    Color color;
    CountDownLatch countDownLatch;

    public Worker(Button button, Color color, CountDownLatch countDownLatch) {
        this.button = button;
        this.color = color;
        this.countDownLatch = countDownLatch;
    }

    @Override
    public void run() {
        button.setBackground(Color.WHITE);
        button.setOpaque(true);

        try {
            Thread.currentThread().sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        button.setBackground(color);
        button.setOpaque(false);
        countDownLatch.countDown();

    }
}

一旦灯光变色1秒钟,您就使用countDownLatch.countDown()倒数闩锁,然后等待countDownLatch.await()倒数到零,外螺纹。