无法使用break语句退出循环

时间:2017-01-21 19:03:59

标签: java multithreading for-loop break

public class Threading extends Thread {
    @Override
    public void run(){
        for (int i=0;i<=5;i++){
            System.out.println(Thread.currentThread().getName()+" reached "+i+" metres");
            if(i==5){
                System.out.println("WINNER IS  "+Thread.currentThread().getName().toUpperCase(Locale.ENGLISH));              
                break;
            }
        }
    }
    public static void main(String[] args) {
        Threading t1=new Threading();
        Threading t2=new Threading();
        Threading t3=new Threading();
        t1.setName("Mohit");
        t2.setName("Hary");
        t3.setName("Himanshu");
        t1.start();
        t2.start();
        t3.start();
    }
}

我想打印首先达到5米的线程名称然后离开循环。但是这个代码发生的事情是for循环运行直到每个线程达到5米并且在到达5米时打印所有线程的名称。请告诉我为什么会发生这种情况,我该如何纠正呢?

2 个答案:

答案 0 :(得分:0)

如何以下列方式使用AtomicBoolean

public static class Threading extends Thread {
    private AtomicBoolean raceFinished;

    public Threading(AtomicBoolean raceFinished) {
        this.raceFinished = raceFinished;
    }

    @Override
    public void run() {
        for (int i = 0; i <= 5; i++) {
            System.out.println(Thread.currentThread().getName() + " reached " + i + " metres");
            if (i == 5) {
                if (raceFinished.getAndSet(true)) {
                    break;
                }
                System.out.println("WINNER IS  " + Thread.currentThread().getName().toUpperCase(Locale.ENGLISH));
                break;
            }
        }
    }

    public static void main(String[] args) {
        AtomicBoolean raceFinished = new AtomicBoolean(false);
        Threading t1 = new Threading(raceFinished);
        Threading t2 = new Threading(raceFinished);
        Threading t3 = new Threading(raceFinished);
        t1.setName("Mohit");
        t2.setName("Hary");
        t3.setName("Himanshu");
        t1.start();
        t2.start();
        t3.start();
    }
}

如果你不想参加&#34;比赛&#34;在找到胜利者后继续,然后在循环开始时添加以下内容:

if (raceFinished.get()) {
    break;
}

答案 1 :(得分:0)

  

但是这个代码发生的事情是for循环运行直到每个线程达到5米并打印所有线程的名称,因为它们达到5米。请告诉我为什么会这样......

每个线程都独立运行。他们所做的只是计数到5并且打印WINNER并且他们不知道其他线程正在做什么或者是否有任何“赢得”他们之前。如果你只想一个线程成为赢家,那么他们需要分享某种状态,以便他们知道哪一个是赢家。

  

......我该如何纠正它?

我认为@ luk2302的答案,共享AtomicBoolean是纠正问题的好方法。单个AtomicBoolean由主线程创建并传递到所有子线程中。

final AtomicBoolean raceFinished = new AtomicBoolean(false);
Threading t1 = new Threading(raceFinished);
Threading t2 = new Threading(raceFinished);
Threading t3 = new Threading(raceFinished);

然后当每个线程运行到循环结束时,只有一个线程能够将AtomicBoolean设置为true并声明自己是赢家。

for (int i = 0; i < 5; i++) {
    // ...
}
// i == 5 here
// this is an atomic operation and will succeed only for 1 thread
if (raceFinished.compareAndSet(false, true)) {
    // this is only printed if raceFinished was false beforehand
    System.out.println("WINNER IS  " + Thread.currentThread().getName());
}

这是如何工作的?单AtomicBoolean在所有线程之间共享。它内部是一个volatile boolean字段和逻辑,用于确保对布尔值进行原子更新。 volatile会设置内存障碍,以便线程可以适当地查看和更新​​共享的布尔字段。这很重要的原因是因为线程程序的性能严重依赖于本地CPU缓存,因此它们可以独立运行并获得高性能。

希望这有帮助。