多线程最常用的两个例子就是:火车票和生产者消费者问题了,本文简单的实现一下卖火车票的例子, 首先创建车票类:
class Ticket implements Runnable{ private int num; private int init = 1; private String lock; public Ticket(int num,String lock){ this.num = num; this.lock = lock; } @Override public void run() { while (true){ //这一行和下面不能交换,不然都是一个窗口把票卖完了 synchronized (lock) { if (init > num) { System.out.println("火车票已经卖完了"); return; } try { //模拟出票过程,否则因为执行太快,大部分被一个线程执行完了 Thread.sleep(20); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + "售出火车票:" + init++); } } } }测试方法:
public static void main(String[] args) throws InterruptedException { String str = "lock"; Ticket ticket = new Ticket(100,str); new Thread(ticket,"窗口A").start(); new Thread(ticket,"窗口B").start(); new Thread(ticket,"窗口C").start(); new Thread(ticket,"窗口D").start(); }最终的指向结果为:
窗口A售出火车票:1 窗口A售出火车票:2 窗口A售出火车票:3 窗口A售出火车票:4 窗口A售出火车票:5 窗口A售出火车票:6 窗口A售出火车票:7 窗口A售出火车票:8 窗口A售出火车票:9 窗口A售出火车票:10 窗口A售出火车票:11 窗口A售出火车票:12 窗口A售出火车票:13 窗口A售出火车票:14 窗口A售出火车票:15 窗口A售出火车票:16 窗口A售出火车票:17 窗口A售出火车票:18 窗口A售出火车票:19 窗口A售出火车票:20 窗口A售出火车票:21 窗口A售出火车票:22 窗口A售出火车票:23 窗口A售出火车票:24 窗口A售出火车票:25 窗口A售出火车票:26 窗口D售出火车票:27 窗口D售出火车票:28 窗口D售出火车票:29 窗口D售出火车票:30 窗口D售出火车票:31 窗口D售出火车票:32 窗口D售出火车票:33 窗口C售出火车票:34 窗口C售出火车票:35 窗口C售出火车票:36 窗口C售出火车票:37 窗口C售出火车票:38 窗口C售出火车票:39 窗口C售出火车票:40 窗口C售出火车票:41 窗口C售出火车票:42 窗口C售出火车票:43 窗口C售出火车票:44 窗口C售出火车票:45 窗口C售出火车票:46 窗口C售出火车票:47 窗口C售出火车票:48 窗口C售出火车票:49 窗口C售出火车票:50 窗口C售出火车票:51 窗口C售出火车票:52 窗口C售出火车票:53 窗口C售出火车票:54 窗口C售出火车票:55 窗口C售出火车票:56 窗口C售出火车票:57 窗口C售出火车票:58 窗口C售出火车票:59 窗口C售出火车票:60 窗口C售出火车票:61 窗口C售出火车票:62 窗口C售出火车票:63 窗口C售出火车票:64 窗口C售出火车票:65 窗口C售出火车票:66 窗口C售出火车票:67 窗口C售出火车票:68 窗口C售出火车票:69 窗口C售出火车票:70 窗口C售出火车票:71 窗口C售出火车票:72 窗口C售出火车票:73 窗口C售出火车票:74 窗口C售出火车票:75 窗口C售出火车票:76 窗口C售出火车票:77 窗口C售出火车票:78 窗口C售出火车票:79 窗口C售出火车票:80 窗口C售出火车票:81 窗口C售出火车票:82 窗口C售出火车票:83 窗口C售出火车票:84 窗口C售出火车票:85 窗口C售出火车票:86 窗口C售出火车票:87 窗口C售出火车票:88 窗口C售出火车票:89 窗口C售出火车票:90 窗口C售出火车票:91 窗口C售出火车票:92 窗口C售出火车票:93 窗口C售出火车票:94 窗口C售出火车票:95 窗口C售出火车票:96 窗口C售出火车票:97 窗口C售出火车票:98 窗口C售出火车票:99 窗口C售出火车票:100 窗口B: 火车票已经卖完了 窗口C: 火车票已经卖完了 窗口D: 火车票已经卖完了 窗口A: 火车票已经卖完
虽然用sleep模拟了出票的过程,但是大部分票都被C窗口卖出去了,这里为了优化可以改成
public void run() { while (true){ synchronized (lock) { if (init > num) { System.out.println(Thread.currentThread().getName()+": 火车票已经卖完了"); return; } try { //模拟出票过程,否则因为执行太快,大部分被一个线程执行完了 lock.wait(30); } catch (InterruptedException e) { e.printStackTrace(); } if (init > num) { System.out.println(Thread.currentThread().getName()+": 火车票已经卖完了"); return; } System.out.println(Thread.currentThread().getName() + "售出火车票:" + init++); } } }这样子出票就很均匀了,而且在一个窗口进行操作的时候不会影响到其它窗口操作,输出就会不会出现大部分集中在一个窗口了。
