BuyTicketThread线程类代码如下所示:
package com.test.test02;
public class BuyTicketThread extends Thread{
static Object o = new Object();//如何确定为一把锁,用static修饰,用static修饰的在内存中是独一份
final String a = "abc"; //这块a变量加final修饰就不能做更改了
public BuyTicketThread(String name) {
super(name);
}
//一共10张票 怎么让这10张票共享?
static int ticketNum = 10; //多个对象共享10张票
//int ticketNum = 10;
//每个窗口都是一个线程对象:每个对象执行的代码放入run方法中
@Override
public void run() {
//每个窗口后面有100个人在抢票
for(int i=1;i<=100;i++) {
//synchronized (this) {
//synchronized ("abc") {
//synchronized (BuyTicketThread.class) {
//synchronized (o) { //用Object对象o作为锁上面的写法是不同的锁,有t1,t2,t3三个对象,对应的o也是不同的锁,对应的o有3个,也是3个锁,加上static就是同一把锁了。
synchronized (a) { //上面的字符串abc在内存中是独一份,也是好使的
//a = "def";
if (ticketNum > 0) {//对票数进行判断,票数大于零我们才抢票
System.out.println("我在" + this.getName() + "买到了从北京到哈尔滨的第" + ticketNum-- + "张车票");
}
}
}
}
public void a() { //两个方法都将o锁住了
synchronized(o) { //这个o被释放了下面的o才能执行
}
}
public void c() {
synchronized(a) { //上面的o被锁住了但是a还能正常执行
}
}
public void b() {
synchronized(o) {
}
}
}
线程测试Test类如下所示:
package com.test.test02;
import com.test.test01.TestThread;
public class Test {
public static void main(String[] args) {
//多个窗口抢票:三个窗口三个线程对象
BuyTicketThread t1 = new BuyTicketThread("窗口1");
t1.start();
BuyTicketThread t2 = new BuyTicketThread("窗口2");
t2.start();
BuyTicketThread t3 = new BuyTicketThread("窗口3");
t3.start();
}
/*
//多运行几次就出现了同时买到第9张车票情况,如下所示:
我在窗口1买到了从北京到哈尔滨的第9张车票
我在窗口3买到了从北京到哈尔滨的第10张车票
我在窗口2买到了从北京到哈尔滨的第9张车票
我在窗口3买到了从北京到哈尔滨的第7张车票
我在窗口1买到了从北京到哈尔滨的第8张车票
我在窗口3买到了从北京到哈尔滨的第5张车票
我在窗口2买到了从北京到哈尔滨的第6张车票
我在窗口3买到了从北京到哈尔滨的第3张车票
我在窗口1买到了从北京到哈尔滨的第4张车票
我在窗口3买到了从北京到哈尔滨的第1张车票
我在窗口2买到了从北京到哈尔滨的第2张车票
//加了synchronized (this)还有问题
我在窗口2买到了从北京到哈尔滨的第10张车票
我在窗口3买到了从北京到哈尔滨的第9张车票
我在窗口1买到了从北京到哈尔滨的第10张车票
我在窗口3买到了从北京到哈尔滨的第7张车票
我在窗口2买到了从北京到哈尔滨的第8张车票
我在窗口3买到了从北京到哈尔滨的第5张车票
我在窗口1买到了从北京到哈尔滨的第6张车票
我在窗口3买到了从北京到哈尔滨的第3张车票
我在窗口2买到了从北京到哈尔滨的第4张车票
我在窗口3买到了从北京到哈尔滨的第1张车票
我在窗口1买到了从北京到哈尔滨的第2张车票
//加了synchronized ("abc")后没有问题了
我在窗口1买到了从北京到哈尔滨的第10张车票
我在窗口1买到了从北京到哈尔滨的第9张车票
我在窗口2买到了从北京到哈尔滨的第8张车票
我在窗口2买到了从北京到哈尔滨的第7张车票
我在窗口2买到了从北京到哈尔滨的第6张车票
我在窗口2买到了从北京到哈尔滨的第5张车票
我在窗口2买到了从北京到哈尔滨的第4张车票
我在窗口2买到了从北京到哈尔滨的第3张车票
我在窗口2买到了从北京到哈尔滨的第2张车票
我在窗口2买到了从北京到哈尔滨的第1张车票
//加了synchronized (BuyTicketThread.class)后也没有问题了
我在窗口1买到了从北京到哈尔滨的第10张车票
我在窗口1买到了从北京到哈尔滨的第9张车票
我在窗口1买到了从北京到哈尔滨的第8张车票
我在窗口3买到了从北京到哈尔滨的第7张车票
我在窗口3买到了从北京到哈尔滨的第6张车票
我在窗口3买到了从北京到哈尔滨的第5张车票
我在窗口3买到了从北京到哈尔滨的第4张车票
我在窗口3买到了从北京到哈尔滨的第3张车票
我在窗口3买到了从北京到哈尔滨的第2张车票
我在窗口3买到了从北京到哈尔滨的第1张车票
*
*
* */
}
该文章通过一个Java多线程的例子展示了如何处理并发问题。BuyTicketThread类模拟了售票窗口,使用synchronized关键字实现线程同步,防止数据竞争。通过尝试使用this、字符串abc、BuyTicketThread.class和静态对象o作为锁,最终发现使用静态对象或类作为锁可以确保线程安全地减少票数,避免了同时卖出多张票的情况。

257

被折叠的 条评论
为什么被折叠?



