我试图用Bruce Eckel的Thinking in Java编译这个例子:
import java.util.concurrent.*;
public class SimplePriorities implements Runnable {
private int countDown = 5;
private volatile double d; // No optimization
private int priority;
public SimplePriorities(int priority) {
this.priority = priority;
}
public String toString() {
return Thread.currentThread() + ": " + countDown;
}
public void run() {
Thread.currentThread().setPriority(priority);
while(true) {
// An expensive, interruptable operation:
for(int i = 1; i < 100000; i++) {
d += (Math.PI + Math.E) / (double)i;
if(i % 1000 == 0)
Thread.yield();
}
System.out.println(this);
if(--countDown == 0) return;
}
}
public static void main(String[] args) {
ExecutorService exec = Executors.newCachedThreadPool();
for(int i = 0; i < 5; i++)
exec.execute(
new SimplePriorities(Thread.MIN_PRIORITY));
exec.execute(
new SimplePriorities(Thread.MAX_PRIORITY));
exec.shutdown();
}
}
根据这本书,输出必须如下:
Thread[pool-1-thread-6,10,main]: 5
Thread[pool-1-thread-6,10,main]: 4
Thread[pool-1-thread-6,10,main]: 3
Thread[pool-1-thread-6,10,main]: 2
Thread[pool-1-thread-6,10,main]: 1
Thread[pool-1-thread-3,1,main]: 5
Thread[pool-1-thread-2,1,main]: 5
Thread[pool-1-thread-1,1,main]: 5
...
但在我的情况下,第6个线程最初不执行任务,线程无序。你能解释一下我有什么问题吗?我只是复制了源代码并没有添加任何代码字符串。
答案 0 :(得分:0)
代码工作正常,并附有书中的输出。
你的IDE可能有滚动条的控制台窗口 - 只需向上滚动它,看第6个线程首先完成它的工作。
但是,结果可能因操作系统/ JVM版本而异。此代码在Windows 10 / JVM 8上按预期运行
答案 1 :(得分:0)
这里有两个问题:
如果两个具有相同优先级的线程想要写输出,哪一个先行?
线程的顺序(具有相同的优先级)是未定义的,因此输出的顺序是未定义的。很可能允许单个线程连续写入多个输出(因为这是大多数线程调度程序的工作方式),但也可能是完全随机的,或介于两者之间的任何内容。
缓存的线程池将创建多少个线程?
这取决于你的系统。如果你在双核系统上运行,创建4个以上的线程毫无意义,因为几乎没有任何CPU可用于执行这些线程。在此方案中,只有在先前的任务完成后,其他任务才会排队并执行。
提示:还有一个固定大小的线程池,试验它应该改变输出。
总而言之,您的代码没有任何问题,假设线程以任何顺序执行是错误的。甚至在技术上可能(尽管非常不可能),第一个任务在最后一个任务开始之前就已经完成了。如果您的图书说上面的订单是&#34;正确&#34;那本书完全错了。在一个可能是最有可能的输出的平均系统上,但是 - 如上所述 - 除了你强制执行它之外,线程永远不会有任何顺序。
强制执行它的一种方法是线程优先级 - 更高优先级将首先完成工作 - 您可以在concurrent package中找到其他概念。