具有最高优先级的Java线程不会被执行

时间:2017-04-24 14:24:25

标签: java multithreading

Main.java:

public class Main {
    public static void main(String[] args) {
        final Semaphore semp = new Semaphore(1);
        for (int facultyNO = 1; facultyNO <= 10; facultyNO++) {
            final int NO = facultyNO;
            Runnable run = new Runnable() {
                public void run() {
                    try {
                        while (true) {
                            semp.acquire();
                            System.out.println("No." + NO + " grab a candy");
                            Bowl.candy--;
                            System.out.println("Candy num left:" + Bowl.candy);
                            semp.release();
                            Thread.sleep((long) (1000));
                        }
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            };
            Thread faculty = new Thread(run);
            faculty.setPriority(Thread.MIN_PRIORITY);
            faculty.start();
        }
        Thread TA = new Thread(() -> {
            try {
                while (true) {
                    if (Bowl.candy < 0) {
                        semp.acquire();
                        System.out.println("TA fills the candy bowl");
                        Bowl.candy = 10;
                        System.out.println("Candy num left:" + Bowl.candy);
                        semp.release();
                    }
                }
            }catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        TA.setPriority(Thread.MAX_PRIORITY);
        TA.start();
    }
}

Bowl.java:

public class Bowl {
    static int candy = 10;
}

我给线程&#34; TA&#34;最高优先级,因为我希望它在Bowl.candy = 0时尽快执行以填充碗。但是,控制台打印:

No.2 grab a candy
Candy num left:9
No.1 grab a candy
Candy num left:8
No.4 grab a candy
Candy num left:7
No.6 grab a candy
Candy num left:6
No.7 grab a candy
Candy num left:5
No.8 grab a candy
Candy num left:4
No.3 grab a candy
Candy num left:3
No.5 grab a candy
Candy num left:2
No.10 grab a candy
Candy num left:1
No.9 grab a candy
Candy num left:0
No.2 grab a candy
Candy num left:-1
No.1 grab a candy
Candy num left:-2
No.4 grab a candy
Candy num left:-3
No.6 grab a candy
Candy num left:-4
No.7 grab a candy
Candy num left:-5
No.8 grab a candy
Candy num left:-6
No.3 grab a candy
Candy num left:-7
No.5 grab a candy
Candy num left:-8
No.10 grab a candy
Candy num left:-9
No.9 grab a candy
Candy num left:-10

似乎if (Bowl.candy < 0)中的代码永远不会被执行。为什么呢?

2 个答案:

答案 0 :(得分:3)

在这种情况下,您必须先获取锁定才能访问变量:

semp.acquire();
if (Bowl.candy < 0) {
    System.out.println("TA fills the candy bowl");
    Bowl.candy = 10;
    System.out.println("Candy num left:" + Bowl.candy);
}
semp.release();

另一种选择:

Bowl.candy必须声明为volatile,否则无法保证其他线程可以看到对此变量的更改。或者只能在Bowl.candy块中访问synchronized

答案 1 :(得分:1)

我怀疑这是一个竞争条件问题。您正在检查该值,然后我怀疑另一个线程已经采用了信号量,因此您无法更改该值。

如果您更改信号量以包装支票和分配,您的结果会稍微好一点。

Thread TA = new Thread(() -> {
    try {
        while (true) {
            semp.acquire();
            if (candy < 0) {
                System.out.println("TA fills the candy bowl");
                Bowl.candy = 10;
                System.out.println("Candy num left:" + Bowl.candy);
            }
            semp.release();
        }
    }
    //...
});

但是,由于时间安排问题,您将获得以下结果:

Candy num left:2
No.2 grab a candy
Candy num left:1
No.3 grab a candy
Candy num left:0
No.5 grab a candy
Candy num left:-1  //!!!
No.6 grab a candy
Candy num left:-2  //!!!
TA fills the candy bowl

正如Nambari指出的那样,你可能不想用多个线程来解决这个问题。