示例代码:多线程安全问题此处通过syncronized关键字实现 也可通过lock上锁实现,在tick类中定义lock属性,在执行售票逻辑前上锁,售票逻辑执行完后在finally块中手动释放锁;
public class SellTickets {
public static void main(String[] args) {
//创建车票对象,并初始化车票总数
Ticket ticket=new Ticket(100);
//创建售票线程 ,并设置窗口名字,然后启动线程,这里设置四个窗口
new Thread(ticket,"窗口A").start();
new Thread(ticket,"窗口B").start();
new Thread(ticket,"窗口C").start();
new Thread(ticket,"窗口D").start();
}
}
/**
* 采用实现Runnable接口的方式实现多线程
*/
class Ticket implements Runnable {
//总的车票数
int total;
Ticket(int total){
this.total=total;
}
//初始车票号码 1
int num = 1;
@Override
public void run() {
while (true) {
synchronized (this) {//多线程安全问题此处通过syncronized关键字实现 也可通过lock上锁实现
try {
// 任何线程获取"线程锁"以后都要先判断是否还有余票,防止等待的线程多打印车票
if (total<=0) return;
// 获取当前线程名字
String threadName = Thread.currentThread().getName();
// 格式化票号
String ticketNum = FormatTicketNum(num++);
// 打印火车票,休眠20毫秒模拟打印车票时间
Thread.sleep(200);
System.out.println(threadName + " 售出火车票No." + ticketNum+"。还剩余票"+--total);
// 某线程售完最后一张车票时,放出"车票已售罄"提示
if (total<=0) {
System.out.println("车票已售罄!");
return;
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
/**
* 格式化车票号码
*/
static String FormatTicketNum(int num) {
NumberFormat nf = NumberFormat.getIntegerInstance();
nf.setMinimumIntegerDigits(3);
return nf.format(num);
}
}
执行结果:
窗口A 售出火车票No.001。还剩余票99
窗口C 售出火车票No.002。还剩余票98
窗口D 售出火车票No.003。还剩余票97
窗口D 售出火车票No.004。还剩余票96
窗口D 售出火车票No.005。还剩余票95
窗口D 售出火车票No.006。还剩余票94
窗口D 售出火车票No.007。还剩余票93
窗口B 售出火车票No.008。还剩余票92
窗口D 售出火车票No.009。还剩余票91
窗口D 售出火车票No.010。还剩余票90
窗口C 售出火车票No.011。还剩余票89
窗口C 售出火车票No.012。还剩余票88
窗口C 售出火车票No.013。还剩余票87
窗口C 售出火车票No.014。还剩余票86
窗口C 售出火车票No.015。还剩余票85
窗口C 售出火车票No.016。还剩余票84
窗口C 售出火车票No.017。还剩余票83
窗口A 售出火车票No.018。还剩余票82
窗口A 售出火车票No.019。还剩余票81
窗口A 售出火车票No.020。还剩余票80
窗口A 售出火车票No.021。还剩余票79
窗口A 售出火车票No.022。还剩余票78
窗口A 售出火车票No.023。还剩余票77
窗口A 售出火车票No.024。还剩余票76
窗口A 售出火车票No.025。还剩余票75
窗口A 售出火车票No.026。还剩余票74
窗口A 售出火车票No.027。还剩余票73
窗口A 售出火车票No.028。还剩余票72
窗口A 售出火车票No.029。还剩余票71
窗口A 售出火车票No.030。还剩余票70
窗口A 售出火车票No.031。还剩余票69
窗口A 售出火车票No.032。还剩余票68
窗口A 售出火车票No.033。还剩余票67
窗口A 售出火车票No.034。还剩余票66
窗口A 售出火车票No.035。还剩余票65
窗口A 售出火车票No.036。还剩余票64
窗口A 售出火车票No.037。还剩余票63
窗口A 售出火车票No.038。还剩余票62
窗口A 售出火车票No.039。还剩余票61
窗口C 售出火车票No.040。还剩余票60
窗口C 售出火车票No.041。还剩余票59
窗口C 售出火车票No.042。还剩余票58
窗口C 售出火车票No.043。还剩余票57
窗口C 售出火车票No.044。还剩余票56
窗口C 售出火车票No.045。还剩余票55
窗口C 售出火车票No.046。还剩余票54
窗口D 售出火车票No.047。还剩余票53
窗口D 售出火车票No.048。还剩余票52
窗口D 售出火车票No.049。还剩余票51
窗口D 售出火车票No.050。还剩余票50
窗口D 售出火车票No.051。还剩余票49
窗口D 售出火车票No.052。还剩余票48
窗口D 售出火车票No.053。还剩余票47
窗口D 售出火车票No.054。还剩余票46
窗口D 售出火车票No.055。还剩余票45
窗口D 售出火车票No.056。还剩余票44
窗口D 售出火车票No.057。还剩余票43
窗口D 售出火车票No.058。还剩余票42
窗口D 售出火车票No.059。还剩余票41
窗口D 售出火车票No.060。还剩余票40
窗口D 售出火车票No.061。还剩余票39
窗口D 售出火车票No.062。还剩余票38
窗口D 售出火车票No.063。还剩余票37
窗口D 售出火车票No.064。还剩余票36
窗口B 售出火车票No.065。还剩余票35
窗口B 售出火车票No.066。还剩余票34
窗口B 售出火车票No.067。还剩余票33
窗口B 售出火车票No.068。还剩余票32
窗口B 售出火车票No.069。还剩余票31
窗口B 售出火车票No.070。还剩余票30
窗口B 售出火车票No.071。还剩余票29
窗口B 售出火车票No.072。还剩余票28
窗口B 售出火车票No.073。还剩余票27
窗口B 售出火车票No.074。还剩余票26
窗口B 售出火车票No.075。还剩余票25
窗口B 售出火车票No.076。还剩余票24
窗口B 售出火车票No.077。还剩余票23
窗口B 售出火车票No.078。还剩余票22
窗口B 售出火车票No.079。还剩余票21
窗口B 售出火车票No.080。还剩余票20
窗口B 售出火车票No.081。还剩余票19
窗口B 售出火车票No.082。还剩余票18
窗口B 售出火车票No.083。还剩余票17
窗口B 售出火车票No.084。还剩余票16
窗口B 售出火车票No.085。还剩余票15
窗口B 售出火车票No.086。还剩余票14
窗口B 售出火车票No.087。还剩余票13
窗口B 售出火车票No.088。还剩余票12
窗口B 售出火车票No.089。还剩余票11
窗口B 售出火车票No.090。还剩余票10
窗口B 售出火车票No.091。还剩余票9
窗口B 售出火车票No.092。还剩余票8
窗口B 售出火车票No.093。还剩余票7
窗口B 售出火车票No.094。还剩余票6
窗口B 售出火车票No.095。还剩余票5
窗口D 售出火车票No.096。还剩余票4
窗口D 售出火车票No.097。还剩余票3
窗口C 售出火车票No.098。还剩余票2
窗口A 售出火车票No.099。还剩余票1
窗口A 售出火车票No.100。还剩余票0
车票已售罄!