线程问题--火车站卖票问题 线程javase单例 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 public class Ticket implements Runnable { private int ticket = 5; public void run() { while (true) synchronized (this) { if (ticket > 0) { System.out.println("顾客到达 " + Thread.currentThread().getName() + "售票台"); System.out.println("售票台" + Thread.currentThread().getName() + "准备出售第" + ticket + "张票"); try {// 具体卖票过程 /*System.out.println("售票台需要5分钟出售这张票"); for (int i = 1; i < 5; i++) { Thread.sleep(1000); System.out.println(i + "分钟"); }*/ System.out.println("售票台" + Thread.currentThread().getName() + "卖完第" + ticket + "张票"); System.out.println("顾客从" + Thread.currentThread().getName() + "买到第" + ticket + "张票"); ticket--; } catch (Exception e) { System.out.println("卖票不成功"); System.exit(1); } } else { break; } } } public static void main(String[] args) { Ticket t = new Ticket(); Thread s = new Thread(t); Thread s1 = new Thread(t); Thread s2 = new Thread(t); Thread s3 = new Thread(t); s.start(); s1.start(); s2.start(); s3.start(); } }稍做了一下修改 这个是同步问题 错票 负票都是没上锁的原因 其实你两个程序都一样有问题,至于你第二个问题没有体现出来是因为时间太短了。第一个里面有sleep,第二个却没有,如果第二个把sleep加上的话,效果会是一样的。按照1楼的方式加锁是可以的。只不过这个锁加的范围有点大了,这样就和单线程没有区别了。可以对程序做一些调整,适当减小加锁的范围。 楼主一开始的两个程序,都是多线程去抢ticket,不上锁肯定会冲突的,楼上说得对,第二个没有出现负数是因为时间太短而已! 试想这么一个场景: 到最后一张票的时候,4个线程同时检查“ticket > 0”进去了,进去了就会卖出来,可是只有一张票,所以出现负数。所以此处重点在于同步好这些ticket。而且考虑到性能问题,把锁的范围缩得越小越好。楼主这里只要加个控制变量 ticketControl 就可以很好解决线程冲突的问题,而且能使效率最大化。class Ticket extends Thread { private volatile int ticket = 5; private volatile int ticketControl = ticket; @Override public void run() { while (true) { if (ticketControl-- > 0) { System.out.println("顾客到达 " + Thread.currentThread().getName() + "售票台"); System.out.println("售票台" + Thread.currentThread().getName() + "准备出售第" + ticket + "张票"); try {// 具体卖票过程 System.out.println("售票台需要5分钟出售这张票"); for (int i = 1; i < 5; i++) { Thread.sleep(100); System.out.println(i + "分钟"); } System.out.println("售票台" + Thread.currentThread().getName() + "卖完第" + ticket + "张票"); System.out.println("顾客从" + Thread.currentThread().getName() + "买到第" + ticket + "张票"); --ticket; } catch (InterruptedException e) { System.out.println("卖票不成功"); System.exit(1); } } else { break; } } }} 我再补充一下,由于“if (ticketControl-- > 0) {”不是原子操作,其实还是有冲突的隐患,所以再加个锁更加稳妥,而且也不怎么影响性能,改成如下:int nTicket = 0; synchronized(this) { nTicket = ticketControl--; } if (nTicket > 0) { 的二个是人品好 多运行几次总会出负的 第一个因为有sleep所以隐患比较明显罢了 当我把第一个的sleep去掉后还是有负票,当我把第二个票数改到2000的时候,还是没有负票。 楼主一开始的两个程序,都是多线程去抢ticket,不上锁肯定会冲突的,楼上说得对,第二个没有出现负数是因为时间太短而已! 试想这么一个场景: 到最后一张票的时候,4个线程同时检查“ticket > 0”进去了,进去了就会卖出来,可是只有一张票,所以出现负数。所以此处重点在于同步好这些ticket。而且考虑到性能问题,把锁的范围缩得越小越好。楼主这里只要加个控制变量 ticketControl 就可以很好解决线程冲突的问题,而且能使效率最大化。class Ticket extends Thread { private volatile int ticket = 5; private volatile int ticketControl = ticket; @Override public void run() { while (true) { if (ticketControl-- > 0) { System.out.println("顾客到达 " + Thread.currentThread().getName() + "售票台"); System.out.println("售票台" + Thread.currentThread().getName() + "准备出售第" + ticket + "张票"); try {// 具体卖票过程 System.out.println("售票台需要5分钟出售这张票"); for (int i = 1; i < 5; i++) { Thread.sleep(100); System.out.println(i + "分钟"); } System.out.println("售票台" + Thread.currentThread().getName() + "卖完第" + ticket + "张票"); System.out.println("顾客从" + Thread.currentThread().getName() + "买到第" + ticket + "张票"); --ticket; } catch (InterruptedException e) { System.out.println("卖票不成功"); System.exit(1); } } else { break; } } }}恩,还没试,但是逻辑上应该正确,,但是你在if里加了个--,下面的--ticket就可以去掉了。你还是太粗心,O(∩_∩)O哈哈~ 楼主一开始的两个程序,都是多线程去抢ticket,不上锁肯定会冲突的,楼上说得对,第二个没有出现负数是因为时间太短而已! 试想这么一个场景: 到最后一张票的时候,4个线程同时检查“ticket > 0”进去了,进去了就会卖出来,可是只有一张票,所以出现负数。所以此处重点在于同步好这些ticket。而且考虑到性能问题,把锁的范围缩得越小越好。楼主这里只要加个控制变量 ticketControl 就可以很好解决线程冲突的问题,而且能使效率最大化。class Ticket extends Thread { private volatile int ticket = 5; private volatile int ticketControl = ticket; @Override public void run() { while (true) { if (ticketControl-- > 0) { System.out.println("顾客到达 " + Thread.currentThread().getName() + "售票台"); System.out.println("售票台" + Thread.currentThread().getName() + "准备出售第" + ticket + "张票"); try {// 具体卖票过程 System.out.println("售票台需要5分钟出售这张票"); for (int i = 1; i < 5; i++) { Thread.sleep(100); System.out.println(i + "分钟"); } System.out.println("售票台" + Thread.currentThread().getName() + "卖完第" + ticket + "张票"); System.out.println("顾客从" + Thread.currentThread().getName() + "买到第" + ticket + "张票"); --ticket; } catch (InterruptedException e) { System.out.println("卖票不成功"); System.exit(1); } } else { break; } } }}恩,还没试,但是逻辑上应该正确,,但是你在if里加了个--,下面的--ticket就可以去掉了。你还是太粗心,O(∩_∩)O哈哈~我用了两个参数呢,两个是不同的!你跑一下就知道了,如果只用一个的话,会冲突,出现负数的票数。用两个就不会了!所以--ticket是要的 我做了一个单机版小游戏,就是不知道怎么改成网络版的,请教一个问题 Javac编译时报:错误:仅当显式请求注释处理时才接受类名称*** 是怎么回事啊? 在后台运行java程序,开war3.exe之后,就不能用runTime.exec()了 菜鸟的一个关于包的小问题。 怎样编辑一个JAVA定时器 java 里有什么方法可以点个按钮就用IE打开指定的网站不?? 用java在LINUX下面怎么获取硬盘序列号、cpu序列号等硬件ID吗? 小问题 请教各位高手,js如何接收applet传来的参数? Sybase用jdbc JConnect 一个简单而有趣的类型转换问题 Jframe 居中问题
public class Ticket implements Runnable {
private int ticket = 5;
public void run() {
while (true)
synchronized (this)
{
if (ticket > 0)
{
System.out.println("顾客到达 "
+ Thread.currentThread().getName() + "售票台");
System.out.println("售票台" + Thread.currentThread().getName()
+ "准备出售第" + ticket + "张票");
try
{// 具体卖票过程
/*System.out.println("售票台需要5分钟出售这张票");
for (int i = 1; i < 5; i++) {
Thread.sleep(1000);
System.out.println(i + "分钟");
}*/
System.out.println("售票台"
+ Thread.currentThread().getName() + "卖完第"
+ ticket + "张票");
System.out.println("顾客从"
+ Thread.currentThread().getName() + "买到第"
+ ticket + "张票");
ticket--;
}
catch (Exception e)
{
System.out.println("卖票不成功");
System.exit(1);
}
}
else
{
break;
}
}
}
public static void main(String[] args) {
Ticket t = new Ticket();
Thread s = new Thread(t);
Thread s1 = new Thread(t);
Thread s2 = new Thread(t);
Thread s3 = new Thread(t);
s.start();
s1.start();
s2.start();
s3.start();
}
}稍做了一下修改 这个是同步问题 错票 负票都是没上锁的原因
第一个里面有sleep,第二个却没有,如果第二个把sleep加上的话,效果会是一样的。按照1楼的方式加锁是可以的。只不过这个锁加的范围有点大了,这样就和单线程没有区别了。可以对程序做一些调整,适当减小加锁的范围。
试想这么一个场景: 到最后一张票的时候,4个线程同时检查“ticket > 0”进去了,进去了就会卖出来,可是只有一张票,所以出现负数。
所以此处重点在于同步好这些ticket。而且考虑到性能问题,把锁的范围缩得越小越好。楼主这里只要加个控制变量 ticketControl 就可以很好解决线程冲突的问题,而且能使效率最大化。class Ticket extends Thread {
private volatile int ticket = 5;
private volatile int ticketControl = ticket;
@Override
public void run() {
while (true) {
if (ticketControl-- > 0) {
System.out.println("顾客到达 "
+ Thread.currentThread().getName() + "售票台");
System.out.println("售票台" + Thread.currentThread().getName()
+ "准备出售第" + ticket + "张票");
try {// 具体卖票过程
System.out.println("售票台需要5分钟出售这张票");
for (int i = 1; i < 5; i++) {
Thread.sleep(100);
System.out.println(i + "分钟");
}
System.out.println("售票台"
+ Thread.currentThread().getName() + "卖完第"
+ ticket + "张票");
System.out.println("顾客从"
+ Thread.currentThread().getName() + "买到第"
+ ticket + "张票");
--ticket;
} catch (InterruptedException e) {
System.out.println("卖票不成功");
System.exit(1);
}
} else {
break;
}
}
}
}
synchronized(this) {
nTicket = ticketControl--;
}
if (nTicket > 0) {
当我把第一个的sleep去掉后还是有负票,当我把第二个票数改到2000的时候,还是没有负票。
试想这么一个场景: 到最后一张票的时候,4个线程同时检查“ticket > 0”进去了,进去了就会卖出来,可是只有一张票,所以出现负数。
所以此处重点在于同步好这些ticket。而且考虑到性能问题,把锁的范围缩得越小越好。楼主这里只要加个控制变量 ticketControl 就可以很好解决线程冲突的问题,而且能使效率最大化。class Ticket extends Thread {
private volatile int ticket = 5;
private volatile int ticketControl = ticket;
@Override
public void run() {
while (true) {
if (ticketControl-- > 0) {
System.out.println("顾客到达 "
+ Thread.currentThread().getName() + "售票台");
System.out.println("售票台" + Thread.currentThread().getName()
+ "准备出售第" + ticket + "张票");
try {// 具体卖票过程
System.out.println("售票台需要5分钟出售这张票");
for (int i = 1; i < 5; i++) {
Thread.sleep(100);
System.out.println(i + "分钟");
}
System.out.println("售票台"
+ Thread.currentThread().getName() + "卖完第"
+ ticket + "张票");
System.out.println("顾客从"
+ Thread.currentThread().getName() + "买到第"
+ ticket + "张票");
--ticket;
} catch (InterruptedException e) {
System.out.println("卖票不成功");
System.exit(1);
}
} else {
break;
}
}
}
}
恩,还没试,但是逻辑上应该正确,,但是你在if里加了个--,下面的--ticket就可以去掉了。
你还是太粗心,O(∩_∩)O哈哈~
试想这么一个场景: 到最后一张票的时候,4个线程同时检查“ticket > 0”进去了,进去了就会卖出来,可是只有一张票,所以出现负数。
所以此处重点在于同步好这些ticket。而且考虑到性能问题,把锁的范围缩得越小越好。楼主这里只要加个控制变量 ticketControl 就可以很好解决线程冲突的问题,而且能使效率最大化。class Ticket extends Thread {
private volatile int ticket = 5;
private volatile int ticketControl = ticket;
@Override
public void run() {
while (true) {
if (ticketControl-- > 0) {
System.out.println("顾客到达 "
+ Thread.currentThread().getName() + "售票台");
System.out.println("售票台" + Thread.currentThread().getName()
+ "准备出售第" + ticket + "张票");
try {// 具体卖票过程
System.out.println("售票台需要5分钟出售这张票");
for (int i = 1; i < 5; i++) {
Thread.sleep(100);
System.out.println(i + "分钟");
}
System.out.println("售票台"
+ Thread.currentThread().getName() + "卖完第"
+ ticket + "张票");
System.out.println("顾客从"
+ Thread.currentThread().getName() + "买到第"
+ ticket + "张票");
--ticket;
} catch (InterruptedException e) {
System.out.println("卖票不成功");
System.exit(1);
}
} else {
break;
}
}
}
}
恩,还没试,但是逻辑上应该正确,,但是你在if里加了个--,下面的--ticket就可以去掉了。
你还是太粗心,O(∩_∩)O哈哈~
我用了两个参数呢,两个是不同的!你跑一下就知道了,如果只用一个的话,会冲突,出现负数的票数。用两个就不会了!所以--ticket是要的