我有几个线程(生产者和消费者)的FizzBuzz问题 我在网上找到了这个解决方案:https://gist.github.com/masudak/5098917 但我担心一个特定的情况,一个糟糕的上下文切换,其中'isStop' 是的,但并非所有生产者都将他们的数字添加到队列中。 这是一个真正的问题吗?或者我错过了什么?
public static AtomicInteger counter = new AtomicInteger(0);
public static ConcurrentLinkedQueue<Integer> queue = new ConcurrentLinkedQueue<Integer>();
public static volatile boolean isStop = false;
public static class Producer implements Runnable{
@Override
public void run() {
while ( true ) {
Integer counterValue = counter.incrementAndGet();
if (counterValue <= 100) {
queue.add(counterValue);
} else {
isStop = true;
break;
}
}
}
}
public static class Consumer implements Runnable{
@Override
public void run() {
while ( true ) {
Integer counterValue = queue.poll();
if ( counterValue == null ){
if(isStop){
break;
}
continue;
}
fizzBuzz(counterValue);
}
}
private void fizzBuzz(Integer value){
if( value % 15 == 0 ){
System.out.println("FizzBuzz:" + value);
} else if( value % 3 == 0 ){
System.out.println("Fizz:" + value);
} else if( value % 5 == 0 ){
System.out.println("Buzz:" + value );
} else {
System.out.println(value);
}
}
}
答案 0 :(得分:0)
尽管格式错误和其他问题,这是恕我直言,实际上是一个有趣的问题。是的,我相信这段代码包含一个理论问题,尽管这个问题难以揭露。但是,如果通过添加一些显式随机Thread.sleep
来修改代码,这将模拟真实世界任务的不同线程性能的意外差异,您可以轻松地看到此问题。然后重现问题,您只需要3个线程:2 Producer
s和一个Consumer
s。同样重要的是,在sleep
Producer
速度增加后,Consumer
的速度变得比单Consumer
的速度慢得多(与Producer
被import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.atomic.AtomicInteger;
public class fizzbuzz {
public static void main(String[] args) {
Thread th1 = new Thread(new Producer());
Thread th2 = new Thread(new Producer());
Thread th4 = new Thread(new Consumer());
th1.start();
th2.start();
th4.start();
}
public static AtomicInteger counter = new AtomicInteger(0);
public static ConcurrentLinkedQueue<Integer> queue = new ConcurrentLinkedQueue<Integer>();
public static volatile boolean isStop = false;
public static class Producer implements Runnable {
@Override
public void run() {
while (true) {
Integer counterValue = counter.incrementAndGet();
final int MAX = 10;
if (counterValue <= MAX) {
final int sleep = ThreadLocalRandom.current().nextInt(200);
try {
Thread.sleep(sleep);
} catch (InterruptedException e) {
e.printStackTrace();
}
queue.add(counterValue);
} else {
isStop = true;
break;
}
}
}
}
public static class Consumer implements Runnable {
@Override
public void run() {
while (true) {
Integer counterValue = queue.poll();
if (counterValue == null) {
if (isStop) {
break;
}
continue;
}
fizzBuzz(counterValue);
}
}
private void fizzBuzz(Integer value) {
if (value % 15 == 0) {
System.out.println("FizzBuzz:" + value);
} else if (value % 3 == 0) {
System.out.println("Fizz:" + value);
} else if (value % 5 == 0) {
System.out.println("Buzz:" + value);
} else {
System.out.println(value);
}
}
}
}
被阻止的原始代码不同/ {操作isStop
s不是)。我还将最大值减小到10以缩短日志。所以这是代码:
isStop
如果您运行此代码几次,您可能会看到如下内容:
1
2
4 嘶嘶声:3 嘶嘶声:6
嗡嗡声:5
7
8
Buzz:10
请注意, 9 缺失。发生这种情况是因为生产者#9的睡眠不仅仅是生产者#10的睡眠,所以在实际添加所有元素之前都会isStop
被提升。
甚至是这样的事情:
1
2 嘶嘶声:3
嗡嗡声:5
4 嘶嘶声:6
7 嘶嘶声:9
8
注意缺少 10 。这是恕我直言,更有趣的是:生产者#9为队列和下一次迭代增加了价值,而生产者#10正在睡觉时提出TensorShape = namedtuple('TensorShape', ['batch_size', 'channels', 'height', 'width'])
标志,因为没有其他东西可以生成。
这类问题的一个明显的解决方法是使用CountDownLatch之类的东西来设置s = [hdr, '-' * 94]
...
s.append('{:<20} {:<30} {:>20} {:>20}'.format(node.kind, node.name, data_shape,
tuple(out_shape)))
,而不是在第一个生产者完成其工作时,而是在最后一个生产者完成工作时。