刚学线程遇到了两个问题,一直想不通

能年 2015-03-02 05:56:42
问题1代码:
public class MyThread extends Thread {
private static int tickets=100;
@Override
public void run() {
while(tickets>0)

System.out.println(getName() + "正在出售第" + (tickets--) + "张票");

}
}
public class MYThreadDemo {
public static void main(String[] args) {
MyThread my1 = new MyThread();
MyThread my2 = new MyThread();
my1.setName("窗口1");
my2.setName("窗口2");
my1.start();
my2.start();

}
}
运行结果:
窗口2正在出售第100张票
窗口1正在出售第100张票
窗口1正在出售第99张票
窗口2正在出售第98张票
窗口1正在出售第97张票
窗口2正在出售第96张票
窗口1正在出售第95张票
后面就省略。
问题1:为什么只是偶尔出现这种问题,但有时候运行情况又是正确?


问题2代码:
public class SellTicket implements Runnable {
// 定义100张票
private int tickets = 100;
@Override
public void run() {
while (true) {
if (tickets > 0) {
System.out.println(Thread.currentThread().getName() + "正在出售第"
+ (tickets--) + "张票");
}
}
}
}
public class SellTicketDemo {
public static void main(String[] args) {
SellTicket st = new SellTicket();
Thread t1 = new Thread(st, "窗口1");
Thread t2 = new Thread(st, "窗口2");
Thread t3 = new Thread(st, "窗口3");
t1.start();
t2.start();
t3.start();
}
}
运行结果是正确的,
问题2:但是不是说CPU操作必须是原子性,它有ticket--却不会出现多个窗口售卖相同票呢?就是线程延时所遇到的问题。


求大神解决啊 一直想不通就是这两个问题 不用讲怎么改进 用锁同步实现我会 主要讲这两个问题出现的原因就行 跪谢!
...全文
416 10 打赏 收藏 转发到动态 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
fengdavid 2015-03-06
  • 打赏
  • 举报
回复
对于第一个问题应该System.out.println操作属于I/O操作,会花费大量的时间,所以导致了你所看到的只是偶尔遇到两个窗口卖相同票的情况,试试将输出先缓存,在线程结束后一次性输出看看。(没做验证请见谅
liangtu 2015-03-06
  • 打赏
  • 举报
回复
用队列,线程安全,初始化长度为100,取出后长度减少,当返回null时,表示票卖完了,如果中间抛异常了还可以把对象加到队列中。

private static BlockingQueue<对象> queue = new ArrayBlockingQueue<对象>(100);
yetian_lin 2015-03-04
  • 打赏
  • 举报
回复
一句java的代码对cpu来说不是只执行一步,例如a = b--; 对cpu来说就是把b的值 取出来——然后给a——把a存进去——把b-1——再把b存进去。没记错应该是分这几步。中间没有锁定之类的是随时都有可能断掉的。
c306081148 2015-03-03
  • 打赏
  • 举报
回复
引用 3 楼 sinat_16569125 的回复:
第二段代码: 你在每一个SellTicket里面都有100张票,相当于每个窗口都给了100张票,窗口间谁先卖谁后卖会乱,但是每个窗口自己卖票的顺序一定是从100到1递减的,所以没有你认为的混乱的问题
你的理解是错误的,实际上第二段代码是3个窗口共同卖那100张票,每个窗口卖票的顺序并不是100到1递减,有可能中间的会跳过,被别的窗口卖了的
sinat_16569125 2015-03-03
  • 打赏
  • 举报
回复
第一段代码: 你只有两个线程,运行哪一个线程是JVM说了算的,两个线程是交替运行的,之所以看起来有的时候没有问题是因为你的线程的数量太少了,如果你的线程多一些,一定会不按照顺序依次执行的现象出现 第二段代码: 你在每一个SellTicket里面都有100张票,相当于每个窗口都给了100张票,窗口间谁先卖谁后卖会乱,但是每个窗口自己卖票的顺序一定是从100到1递减的,所以没有你认为的混乱的问题 第一个回复: 你的理解是错误的,JVM相当于是一个虚拟机,JVM里面运行的代码和计算机有几个核是没有关系的
37度冬天 2015-03-03
  • 打赏
  • 举报
回复
第一个问题,访问全局变量线程不安全,出现原因是因为,当线程1执行ticket=100时,在没有真正执行后面的打印部分之前,ticket仍然等于100,此时cpu切换到线程2,它看到的ticket也等于100,因此会出现你说的问题,只要锁同步就行 第二个问题,就是你自己说的,他们三个在同卖那个ticket,cpu操作肯定是原子性的 望给分啊
u012569996 2015-03-03
  • 打赏
  • 举报
回复
多线程同时访问同一个全局变量,当然会线程安全的问题了。
public class Test extends Thread{
	private static int tickets = 100;
	
	private String name;
	
	public Test(String name){
		this.name=name;
	}
	
	private static synchronized int sellOneTicket(){
		return tickets--;
	}
	
	private static boolean haveTicket(){
		boolean b = false;
		if(tickets>0){
			b=true;
		}
		return b;
	}
	
	@Override
	public void run() {
		while(Test.haveTicket()){
			System.out.println(this.name + "正在出售第" + sellOneTicket() + "张票");
		}
	}

	//Main方法
	public static void main(String[] args){
		Test t1 = new Test("窗口1");
		Test t2 = new Test("窗口2");
		t1.start();
		t2.start();
	}
}
运行结果: 窗口1正在出售第100张票 窗口1正在出售第99张票 窗口1正在出售第98张票 窗口1正在出售第97张票 窗口1正在出售第95张票 窗口2正在出售第96张票 窗口1正在出售第94张票 窗口2正在出售第93张票 窗口1正在出售第92张票 窗口2正在出售第91张票 窗口1正在出售第90张票 窗口2正在出售第89张票 窗口1正在出售第88张票 窗口2正在出售第87张票 窗口1正在出售第86张票 窗口2正在出售第85张票 窗口1正在出售第84张票 窗口2正在出售第83张票 本人I7处理器 4核。
黄橙蓝 2015-03-02
  • 打赏
  • 举报
回复
我觉得,把票数定义在线程里是不对的,这样子不就是各个线程启动后,处理的都是各自的票数吗? 改成下面这样,放在主线程里定义,就不会出错。
class MyThread extends Thread {
	private int num;
	public MyThread(int num){this.num=num;}
	@Override
	public void run() {
		while(num>0) 
	
		System.out.println(getName() + "正在出售第" + (num--) + "张票");
	
	}
}
public class Test2 {
	public static void main(String[] args) {
		final int num=100;
		MyThread my1 = new MyThread(num);
		MyThread my2 = new MyThread(num);
		my1.setName("窗口1");
		my2.setName("窗口2");
		my1.start();
		my2.start();

	}
}
疯狂熊猫人 2015-03-02
  • 打赏
  • 举报
回复
个人认为单核cpu不会出现不正常的情况,多核cpu会出现不正常情况。 原因: 1、单核cpu执行多线程实际上是来回切换执行线程(1线程执行了一次,切换到2线程执行,甚至于连续执行某个线程),由于是单核,所以第二次执行的线程必然等到第一次完成后才有机会执行(必然出现时间差)。 2、多核cpu,cpu1执行的时候,cpu2同样可以执行,那么这时就可能出现同时操作tickets的情况,就是你打印出来的“窗口2正在出售第100张票” 说的不对望指正,个人对cpu如何执行指令没有研究过。

62,614

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧