【问题标题】:How can I have one thread do some work and the have another thread join and finish the work?我怎样才能让一个线程做一些工作,让另一个线程加入并完成工作?
【发布时间】:2013-12-22 13:14:51
【问题描述】:

我目前正在尝试学习线程的使用,我发现了一个关于我正在尝试编码的线程的练习。

这是练习:

  1. 创建一个模拟 400 米赛跑的应用程序。

  2. 创建五个线程组并给出名称(国家名称)。

  3. 跑步者的数量应该是(每组两个),并为每个跑步者线程命名。

  4. 每个线程应该跑完一半的距离 - 200 m,并且同一组中的下一个线程应该加入比赛以完成它。

  5. 打印获胜者组名(),所有线程都应该完成比赛。

  6. 打印每个组完成比赛所用的时间并突出显示获胜者的时间。

所以,我的问题是关于每个线程应该跑一半距离的第 4 点,我怎样才能让我的初始线程完成并让下一个线程替换它并完成比赛?

这是我目前的代码:

public class RelayRacerDemo {

public static Thread runner[];

public static void main(String[] args) {
    RelayRacer rRacer = new RelayRacer();

    ThreadGroup country[] = new ThreadGroup[5];
    country[0] = new ThreadGroup("USA");
    country[1] = new ThreadGroup("Mexico");
    country[2] = new ThreadGroup("Italia");
    country[3] = new ThreadGroup("France");
    country[4] = new ThreadGroup("Brazil");

    runner = new Thread[10];
    runner[0] = new Thread(country[0] , rRacer, "USA racer 1");
    runner[1] = new Thread(country[0] , rRacer, "USA racer 2");
    runner[2] = new Thread(country[1] , rRacer, "Mexico racer 1");
    runner[3] = new Thread(country[1] , rRacer, "Mexico racer 2");
    runner[4] = new Thread(country[2] , rRacer, "Italia racer 1");
    runner[5] = new Thread(country[2] , rRacer, "Italia racer 2");
    runner[6] = new Thread(country[3] , rRacer, "France racer 1");
    runner[7] = new Thread(country[3] , rRacer, "France racer 2");
    runner[8] = new Thread(country[4] , rRacer, "Brazil racer 1");
    runner[9] = new Thread(country[4] , rRacer, "Brazil racer 2");

    runner[0].start();
    runner[2].start();
    runner[4].start();
    runner[6].start();
    runner[8].start();
}

}

还有我的可运行代码:

public class RelayRacer implements Runnable{

public static Boolean winnerYet = false;

public void relayRace(){
    for(int distance=1; distance<=40; distance++){
        System.out.println("current runner " + Thread.currentThread().getName() 
                            + " has run " + distance + " meters");
        if(Thread.currentThread().getName().equals("USA racer 1") && distance == 20){
            threadJoin(distance, 1);
        }else if(Thread.currentThread().getName().equals("Mexico racer 1") && distance == 20){
            threadJoin(distance, 3);
        }else if(Thread.currentThread().getName().equals("Italia racer 1") && distance == 20){
            threadJoin(distance, 5);
        }else if(Thread.currentThread().getName().equals("France racer 1") && distance == 20){
            threadJoin(distance, 7);                
        }else if(Thread.currentThread().getName().equals("Brazil racer 1") && distance == 20){
            threadJoin(distance, 9);        
        }

        if(isGroupRacerWinner(distance)){
            System.out.println("Winning Country is " + Thread.currentThread().getThreadGroup().getName());
        }
    }
}


public void threadJoin(int distance, int nextRunner){

        RelayRacerDemo.runner[nextRunner].start();

        try 
        {RelayRacerDemo.runner[nextRunner].join();
        }catch (InterruptedException e) {e.printStackTrace();}

}

public Boolean isGroupRacerWinner(int distance){

    if(distance == 40 && winnerYet == false){
        winnerYet = true;
        return true;
    }else
        return false;
}

@Override
public void run(){
    this.relayRace();
}
}

我把它改成了 40 米,这样我可以更容易地调试我的代码,

runner = thread;

是这样的:每个国家的第一个跑者跑完前 20 米,然后第二个跑者加入比赛,跑完整个比赛(全部 40 米,当它应该只跑 20- 的一半时) 40米。)第二个跑者跑完后,第一个跑者继续比赛,从20-40跑剩下的20米,(应该在半场停下的时候。)

【问题讨论】:

  • 如果您需要通过Thread 获取计算结果,则不需要使用Thread.join()。你也可以use a future

标签: java multithreading


【解决方案1】:

你的代码现在在做什么:

  • 一位跑者跑到 20 点。
  • 然后他开始下一个线程,join() 让他等到 新启动的线程结束。
  • 第二个线程现在执行 for 循环,但因为它是一个新的 例如,它也从 1 开始,一直持续到 40。
  • 然后它就结束了,第一个线程继续执行(它 在 for 循环的第 20 次迭代中)。

所以最终你会得到 20-40-20 次跑步。

您需要确保第二个跑步者不会从一个开始,并且第一个跑步者在呼叫第二个跑步者后完成。

您无需每次迭代都检查团队是否使用isGroupRacerWinner(distance) 获胜。在for 循环之后检查一次就足够了。因为团队只有完成for 循环才有机会获胜。

【讨论】:

  • 是的,你是对的,我在询问之前进行了研究,发现我运行了 20-40-20 次(正如我的问题末尾所解释的那样。)但是,回到我的问题,我怎样才能让我的初始线程完成,然后让下一个替换它并完成比赛?让第二名跑步者从 20 米处开始是一个好点,但这正是我想要做的。
  • 你可以让它们都运行到 20 而不是 40。然后你的第一个线程会等待你的第二个线程并且同时完成。或者,您只需将break; 添加到循环中,以便第一个线程在调用第二个线程后完成。但是你需要弄清楚如何在 20 岁开始第二个。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-12-24
  • 2014-10-21
  • 1970-01-01
  • 1970-01-01
  • 2014-08-19
相关资源
最近更新 更多