一个关于多线程同步的问题。
问题:假设有火车票1000张,创建10个线程模拟10个售票点,每个售票点100毫秒买一张票。打印出售票过程,注意使用synchronized确保同一张票只能卖出一次。输出格式如下:
第4售票点卖出第100张票
第2售票点卖出第101张票 ……
我的解答是:
package ti2;
public class TicketsSell implements Runnable {
static int tickets = 1;
int num;
public TicketsSell(int num) {
this.num = num;
}
public synchronized void run() {
for (; tickets <= 100; tickets++) {
System.out.println("第" + num + "售票点卖出第" + tickets + "张票");
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
package ti2;
public class Station {
public static void main(String[] args) {
Thread wicket1 = new Thread(new TicketsSell(1));
Thread wicket2 = new Thread(new TicketsSell(2));
Thread wicket3 = new Thread(new TicketsSell(3));
Thread wicket4 = new Thread(new TicketsSell(4));
Thread wicket5 = new Thread(new TicketsSell(5));
Thread wicket6 = new Thread(new TicketsSell(6));
Thread wicket7 = new Thread(new TicketsSell(7));
Thread wicket8 = new Thread(new TicketsSell(8));
Thread wicket9 = new Thread(new TicketsSell(9));
Thread wicket10 = new Thread(new TicketsSell(10));
wicket1.start();
wicket2.start();
wicket3.start();
wicket4.start();
wicket5.start();
wicket6.start();
wicket7.start();
wicket8.start();
wicket9.start();
wicket10.start();
}
}
运行结果就是不对!!其中老是出现不同售票点卖出同一张票!请各位高手指点指点!
----------------解决方案--------------------------------------------------------
程序修改如下:我把2个类放在一个包中了,synchronized不应在run方法中!
试下!
class TicketsSell implements Runnable {
static int tickets=1;
int num;
public TicketsSell(int num) {
this.num = num;
}
public void run() {
synchronized(this){
for (int i=0; i< 100; i++) {
if(tickets<101) {
try {
Thread.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("第" + num + "售票点卖出第" + (tickets++) + "张票");
}
}
}
}
}
public class Station {
public static void main(String[] args) {
Thread wicket1 = new Thread(new TicketsSell(1));
Thread wicket2 = new Thread(new TicketsSell(2));
Thread wicket3 = new Thread(new TicketsSell(3));
Thread wicket4 = new Thread(new TicketsSell(4));
Thread wicket5 = new Thread(new TicketsSell(5));
Thread wicket6 = new Thread(new TicketsSell(6));
Thread wicket7 = new Thread(new TicketsSell(7));
Thread wicket8 = new Thread(new TicketsSell(8));
Thread wicket9 = new Thread(new TicketsSell(9));
Thread wicket10 = new Thread(new TicketsSell(10));
wicket1.start();
wicket2.start();
wicket3.start();
wicket4.start();
wicket5.start();
wicket6.start();
wicket7.start();
wicket8.start();
wicket9.start();
wicket10.start();
}
}
----------------解决方案--------------------------------------------------------
程序代码:
public class TicketsShop extends JApplet {
private AtomicInteger ticketNum = new AtomicInteger(0);
private int ticketNum2 = 0;
public int sell() {
return ticketNum.getAndIncrement();
}
public synchronized int sell2() {
ticketNum2++;
return ticketNum2;
}
public void test2() {
long start = System.currentTimeMillis();
List<TicketsSell2> t2 = new ArrayList<TicketsSell2>();
for (int i = 0; i < 10; i++) {
TicketsSell2 t = new TicketsSell2(i+1);
t2.add(t);
t.start();
}
for(TicketsSell2 t : t2){
try {
t.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
long end = System.currentTimeMillis();
System.out.println(end - start);
}
public void test1() {
long start = System.currentTimeMillis();
TicketsSell wicket1 = new TicketsSell(1);
TicketsSell wicket2 = new TicketsSell(2);
TicketsSell wicket3 = new TicketsSell(3);
TicketsSell wicket4 = new TicketsSell(4);
TicketsSell wicket5 = new TicketsSell(5);
TicketsSell wicket6 = new TicketsSell(6);
TicketsSell wicket7 = new TicketsSell(7);
TicketsSell wicket8 = new TicketsSell(8);
TicketsSell wicket9 = new TicketsSell(9);
TicketsSell wicket10 = new TicketsSell(10);
wicket1.start();
wicket2.start();
wicket3.start();
wicket4.start();
wicket5.start();
wicket6.start();
wicket7.start();
wicket8.start();
wicket9.start();
wicket10.start();
try {
wicket1.join();
wicket2.join();
wicket3.join();
wicket4.join();
wicket5.join();
wicket6.join();
wicket7.join();
wicket8.join();
wicket9.join();
wicket10.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
long end = System.currentTimeMillis();
System.out.println(end - start);
}
public static void main(String[] args) {
TicketsShop shop = new TicketsShop();
// shop.test1();
shop.test2();
}
class TicketsSell extends Thread {
int num;
int count = 0;
public TicketsSell(int num) {
this.num = num;
}
public void run() {
while (count < 100) {
int ticketNum = sell() + 1;
System.out.println("第" + num + "售票点卖出第" + ticketNum + "张票");
count++;
try {
Thread.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class TicketsSell2 extends Thread {
int num;
int count = 0;
public TicketsSell2(int num) {
this.num = num;
}
public void run() {
while (count < 100) {
System.out.println("第" + num + "售票点卖出第" + sell2() + "张票");
count++;
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
private AtomicInteger ticketNum = new AtomicInteger(0);
private int ticketNum2 = 0;
public int sell() {
return ticketNum.getAndIncrement();
}
public synchronized int sell2() {
ticketNum2++;
return ticketNum2;
}
public void test2() {
long start = System.currentTimeMillis();
List<TicketsSell2> t2 = new ArrayList<TicketsSell2>();
for (int i = 0; i < 10; i++) {
TicketsSell2 t = new TicketsSell2(i+1);
t2.add(t);
t.start();
}
for(TicketsSell2 t : t2){
try {
t.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
long end = System.currentTimeMillis();
System.out.println(end - start);
}
public void test1() {
long start = System.currentTimeMillis();
TicketsSell wicket1 = new TicketsSell(1);
TicketsSell wicket2 = new TicketsSell(2);
TicketsSell wicket3 = new TicketsSell(3);
TicketsSell wicket4 = new TicketsSell(4);
TicketsSell wicket5 = new TicketsSell(5);
TicketsSell wicket6 = new TicketsSell(6);
TicketsSell wicket7 = new TicketsSell(7);
TicketsSell wicket8 = new TicketsSell(8);
TicketsSell wicket9 = new TicketsSell(9);
TicketsSell wicket10 = new TicketsSell(10);
wicket1.start();
wicket2.start();
wicket3.start();
wicket4.start();
wicket5.start();
wicket6.start();
wicket7.start();
wicket8.start();
wicket9.start();
wicket10.start();
try {
wicket1.join();
wicket2.join();
wicket3.join();
wicket4.join();
wicket5.join();
wicket6.join();
wicket7.join();
wicket8.join();
wicket9.join();
wicket10.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
long end = System.currentTimeMillis();
System.out.println(end - start);
}
public static void main(String[] args) {
TicketsShop shop = new TicketsShop();
// shop.test1();
shop.test2();
}
class TicketsSell extends Thread {
int num;
int count = 0;
public TicketsSell(int num) {
this.num = num;
}
public void run() {
while (count < 100) {
int ticketNum = sell() + 1;
System.out.println("第" + num + "售票点卖出第" + ticketNum + "张票");
count++;
try {
Thread.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class TicketsSell2 extends Thread {
int num;
int count = 0;
public TicketsSell2(int num) {
this.num = num;
}
public void run() {
while (count < 100) {
System.out.println("第" + num + "售票点卖出第" + sell2() + "张票");
count++;
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
----------------解决方案--------------------------------------------------------
其实最好的方法是Lock来做
----------------解决方案--------------------------------------------------------
回复 2楼 w123012306
首先谢谢你的解答。因为在实际卖票活动中,票号必须是从小到大地卖出的,所以你这个还是有点问题! ----------------解决方案--------------------------------------------------------