【问题标题】:Two threads finishing at the same time and accessing the same method两个线程同时完成并访问相同的方法
【发布时间】:2015-07-06 13:22:35
【问题描述】:

我正在学习 Java 中的多线程,所以现在我正在创建经典的龟兔赛跑应用程序。

对于那些不熟悉这个问题的人,基本上有两个赛车手:

  • 一只野兔每圈跑 100 米,但有 90% 的机会休息而不是奔跑
  • 一只乌龟,每圈跑 10 米,但从不休息

第一个达到 1000 米的为获胜者。

我的代码现在看起来像这样:

主类:

public class THRace {

    static Thread hare      = new Thread(new ThreadRunner("Hare",       90, 100));
    static Thread tortoise  = new Thread(new ThreadRunner("Tortoise",   0,  10));

    public static void main(String[] args) {
        hare.start();
        tortoise.start();
    }

    public static void finished(Thread winner){
        if (winner.getName().equals("Hare")) tortoise.interrupt();
        else if (winner.getName().equals("Tortoise")) hare.interrupt();    
    }

}

ThreadRunner 类:

import java.util.Random;

public class ThreadRunner implements Runnable {

    private String name;
    private int rest, speed;

    public String getRacerName() {
        return name;
    }

    public ThreadRunner(String name, int rest, int speed) {
        this.name = name;
        this.rest = rest;
        this.speed = speed;
    }

    @Override
    public void run() {

        int meters = 0;
        Random rn = new Random();

        Thread ct = Thread.currentThread();
        ct.setName(name);

        while(!ct.isInterrupted()){
            if(rn.nextInt(100) + 1 > rest){
                meters += speed;
                System.out.println(this.name + ": " + meters);                
            }

            try {
                Thread.sleep(100);
            }catch (InterruptedException ex){
                return;
                //break;
            }

            if(meters >= 1000){
                System.out.println(this.name + ": I finished!");
                THRace.finished(ct);
                return;
            }

        }
    }

}

当一个线程到达 1000 米时,它会从主类调用 finished 方法并停止另一个线程。我的代码工作得很好,但问题是当出现平局时会发生什么(当兔子和乌龟在同一条平局中达到 1000 米时),两个跑步者都被宣布为赢家,我不希望这种情况发生。

例如,您可以将跑步者设置为 0% 的休息机会和相同的速度,这样他们将同时达到 1000 米:

static Thread hare      = new Thread(new ThreadRunner("Hare",       0,  10));
static Thread tortoise  = new Thread(new ThreadRunner("Tortoise",   0,  10));

输出将是:

(...)
Tortoise: 950
Hare: 950
Hare: 960
Tortoise: 960
Tortoise: 970
Hare: 970
Tortoise: 980
Hare: 980
Tortoise: 990
Hare: 990
Tortoise: 1000
Hare: 1000
Hare: I finished!
Tortoise: I finished!

有没有办法让我“锁定” finished 方法,因此只有一个线程被宣布为获胜者?

【问题讨论】:

标签: java multithreading


【解决方案1】:

如果你在finished方法前面使用synchronized标识符,第一个调用它的线程会锁定它直到它完成。由于您正在中断另一个线程,因此这对您来说应该很好。

synchronized public static void finished(Thread winner){
    if(winner.isInterrupted()) {
        // sorry, the other thread beat you here
        return;
    }

    if (winner.getName().equals("Hare")) tortoise.interrupt();
    else if (winner.getName().equals("Tortoise")) hare.interrupt();    
}

正如您在评论中提到的,如果另一个线程已经排队等待进入完成的方法,您需要添加一个检查以查看您是否被打断,然后再宣布自己为赢家。

【讨论】:

  • 哦,谢谢。我曾尝试使用 synchronized 但一开始并没有奏效,所以我认为我做错了什么并且以错误的方式。但是根据您的回答,我试图找出我的错误:我只需要在打印获胜者之前添加一个条件 "if(!ct.isInterrupted()) System.out.println(this.name + ": I finished!" );"在 ThreadRunner 类中。您能否将此添加到您的答案中,以便其他人更容易看到它?
猜你喜欢
  • 2011-12-31
  • 1970-01-01
  • 2013-10-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多