代码问题。(新开)

代码问题。(新开)

Queue

public class Queue {
	private int n;
	boolean flag = false; // 判断有没有商品,默认没有商品,要先生产

	// 消费
	public synchronized int getN() {
		/*
		 * if (flag ==false) { try { wait(); } catch (InterruptedException e) { // TODO
		 * Auto-generated catch block e.printStackTrace(); } }
		 */
		if (flag == true) {
			System.out.println("消费:" + n);
			flag = false;
		}
		// notifyAll();
		return n;
	}

	// 生产
	public synchronized void setN(int n) {
		/*
		 * if (flag == true) { try { wait(); } catch (InterruptedException e) { // TODO
		 * Auto-generated catch block e.printStackTrace(); } }
		 */
		if (flag == false) {
			System.out.println("生产:" + n);
			this.n = n;
			flag = true;
			// notifyAll();
		}
	}

}

Producer

public class Producer implements Runnable {
	Queue queue;
	
	public Producer(Queue queue) {
		this.queue=queue;
	}

	@Override
	public void run() {
		int i=0;
		while(true) {
			queue.setN(i++);
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}

	}

}

Consumer

public class Consumer implements Runnable {
	Queue queue;
	
	public Consumer(Queue queue) {
		this.queue=queue;
	}

	@Override
	public void run() {
		while(true) {
			queue.getN();
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}

	}
}

Test

public class Test {

	public static void main(String[] args) {
		Queue queue=new Queue();
		new Thread(new Producer(queue)).start();
		
		new Thread(new Consumer(queue)).start();

	}

}

http://img1.sycdn.imooc.com//climg/5ea115b609d500f605540196.jpg

为什么会出现这种情况呢??

正在回答

登陆购买课程后可参与讨论,去登陆

1回答

同学你好,因为同学将线程等待以及线程唤醒的代码都注释掉了,如下图:

http://img1.sycdn.imooc.com//climg/5ea11ddc0969b6f711290142.jpg

所以线程在执行时此线程不会进入等待。

下图是为了测试而写。我们将生产者沉睡时间调整到200ms并打印i的值发现,我们在运行消费者线程时,生产者不会锁死还会继续运行,所以代码会出现打印n的值衔接不上的情况。

注:调整沉睡时间的原因是为了让效果更明显。之前sleep沉睡时间一样,但是由于电脑性能等原因,生产者方法先沉睡,先唤醒,因为同学将wait代码注释,所以会导致没有被wait方法终止,run方法很可能先抢占资源,就会再执行一次,导致i的值多加了一次,最后出现同学运行的效果。

http://img1.sycdn.imooc.com//climg/5ea11e53095974e108370529.jpg

如果我的回答解决了你的疑惑,请采纳,祝学习愉快~

  • 慕容2892559 提问者 #1
    emmmm,有点不明白,i的值为2之后不是应该sleep了么?为什么又出现这么多i的值啊?
    2020-04-23 13:17:25
  • 同学你好,生产者的run方法执行后,是会sleep,也就是当i = 2时生产者执行run方法后,会sleep。但是cpu此时没有选中消费者,因为cpu选中线程也是需要时间的,有可能很快选中消费者,也有可能在生产者沉睡时间内没有选中消费者,所以消费者线程的run方法不会执行。但当生产者的sleep结束时,生产者会再一次和消费者一起抢占cpu资源,如果是生产者抢占到资源,生产者的run方法就会再一次执行,所以i的值会继续增加。而现在出现的情况都是不固定发生的,所以需要我们用wait()和notify()来实现线程通信,保证一次生产,一次消费。 如果我的回答解决了你的疑惑,请采纳,祝学习愉快~
    2020-04-23 13:55:15
问题已解决,确定采纳
还有疑问,暂不采纳

恭喜解决一个难题,获得1积分~

来为老师/同学的回答评分吧

0 星
请稍等 ...
意见反馈 帮助中心 APP下载
官方微信

在线咨询

领取优惠

免费试听

领取大纲

扫描二维码,添加
你的专属老师