前置条件:
设置总票数 ,比如20张
开启多个售票窗口同时进行火车票的售卖 (这里多个窗口代表 多线程. 代表启动了多少个线程对象)
怎么卖票 ? 借助循环 重复卖票动作 ,使用 while死循环
每卖出1张 ,总票数 – 操作 .
什么时候退出循环?
发现卖完了,退出循环
开启线程 ,执行 run方法内部逻辑
单线程卖票 ,是没问题的 .多线程卖票,就出现了并发问题 . 要解决该问题 ,需要使用"同步操作"
synchronized() 括弧内部是 同步锁对象 .
public static void main(String[] args) {
Seller s = new Seller();
Thread a = new Thread(s);
a.setName("1号售票窗口");
a.start();
Thread b = new Thread(s);
b.setName("2号售票窗口");
b.start();
Thread c = new Thread(s);
c.setName("3号售票窗口");
c.start();
}
public class Seller implements Runnable {
private int num = 200;
public void run() {
String name = Thread.currentThread().getName();
for (int i = 0; i < 100; i++) {
if (this.num > 0) {
System.out.println(name + " 卖票,当前卖出的票号为: " + this.num--);
}
}
}
}
总结:
线程的创建
方式1: 继承Thread类
继承Thread 实现多线程
需要重写run方法 . 线程执行的逻辑代码需要放到 run方法 ,比如 迅雷下载逻辑的实现 ,或者 完成 乘法运算
启动线程 start()
方式2: 实现 Runnable接口 ,重写run方法
方式1和方式2的区别: 方式1已经继承Thread类,不能再继承别的类 .方式2还可以继承别的类
方式3: 实现 Callable接口
需要重写 call 方法 ,有返回值 . 注意:如果不限定Callable 的泛型 ,代表通用数据类型
和方式2区别: 可以拿到返回值 ,但是需要处理异常 . 代码写起来麻烦