首页 文章

两个线程同时完成并访问相同的方法

提问于
浏览
4

我正在学习Java中的多线程,所以现在我正在创建经典的Tortoise和Hare竞赛应用程序 .

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

  • 一只野兔在每个循环中跑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 方法,并停止另一个线程 . 我的代码工作正常,但问题是当's a tie (when the hare and the tortoise reach 1000 meters at the same tie), both runners are declared a winner and I don't想要发生这种情况时会发生什么 .

例如,您可以将跑步者设置为具有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 finished 方法,所以只有一个线程被宣布为赢家?

1 回答

  • 7

    如果在完成的方法前面使用 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();    
    }
    

    正如你的评论中所提到的,如果另一个线程已经排队等待进入已完成的方法,你需要添加一个检查,看看你是否在宣布自己是胜利者之前被打断了 .

相关问题