忘掉Java多线程,我们来看看现实生活中的例子

由卖票引发的思考

热门景区往往会开设多个售票窗口,一是为了同时接待更大的客流量,而是为了防止一个售票窗口机器出现故障导致所有人都买不了票。这里引出多线程中最重要的概念之一,阻塞。

实际上,在单核中运行多线程不一定比单线程要快,因为cpu需要调度和切换线程,那我们会什么要使用多线程?实际上使用多线程技术的一个重要原因就是——防止单个线程可能出现阻塞,导致整个工程无法向下继续运行。回顾一下你们自己项目使用多线程的场景,是不是也是因为有可能出现组塞的情况才使用多线程呢?如果不存在线程可能会阻塞的情况,那么是完全没有必要使用多线程的,这便是使用多线程的一个非常重要的前提——阻塞。下面我们用代码来模拟一下单窗口和多窗口售票的情景:

//只有一个窗口售票
public class SimpleStation {

private static int ticks = 20;

public static void main(String[] args) {
    while (ticks > 0) {
        if (ticks == 15) {
            // 这里模拟售票机器故障
            throw new RuntimeException("machine down...");
        }
        ticks --;
        System.out.println("卖了一张票,还剩下:" + ticks + "张票");
    }
}
}

运行结果:

卖了一张票,还剩下:19张票
卖了一张票,还剩下:18张票
卖了一张票,还剩下:17张票
卖了一张票,还剩下:16张票
卖了一张票,还剩下:15张票
Exception in thread "main" java.lang.RuntimeException: machine down...
    at SimpleStation.main(SimpleStation.java:9)

Process finished with exit code 1

从上面运行结果我们可以看到在余票还有15张票的时候,由于唯一售票的机器发生故障之后,剩余15张票就卖不出去了。接下来我们用多线程来解决这个问题:

public class Station extends Thread {

static int ticks = 20;

static Object obj = "LOCK";

public Station(String name) {
    super(name);
}

@Override
public void run() {
        while (ticks > 0) {
            System.out.println(getName() + "卖票中");
            try {
                sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            if (totalTick > 15 && getName().equals("window1")) {
                // 这里模拟窗口1的售票机器发生故障
                throw new RuntimeException(getName() + "发生故障了");
            }
            synchronized (obj) {
                if (totalTick > 0) {
                    // 这里totalTick为受限共享资源
                    totalTick--;
                    System.out.println(getName() + "票卖了1张,还剩:" + totalTick + "张票");
                } else {
                    System.out.println(getName() + "今天的票卖完了");
                }
            }
        }
}
}

运行结果:

window2卖票中
window3卖票中
window1卖票中
window3票卖了1张,还剩:19张票
window3卖票中
window2票卖了1张,还剩:18张票
window2卖票中
Exception in thread "window1" java.lang.RuntimeException: window1发生故障了
    at Station.run(MainClass.java:21)
window3票卖了1张,还剩:17张票
window3卖票中
window2票卖了1张,还剩:16张票
window2卖票中
window3票卖了1张,还剩:15张票
window3卖票中
window2票卖了1张,还剩:14张票
window2卖票中
window3票卖了1张,还剩:13张票
window3卖票中
window2票卖了1张,还剩:12张票
window2卖票中
window3票卖了1张,还剩:11张票
window3卖票中
window2票卖了1张,还剩:10张票
window2卖票中
window3票卖了1张,还剩:9张票
window3卖票中
window2票卖了1张,还剩:8张票
window2卖票中
window3票卖了1张,还剩:7张票
window3卖票中
window2票卖了1张,还剩:6张票
window2卖票中
window3票卖了1张,还剩:5张票
window3卖票中
window2票卖了1张,还剩:4张票
window2卖票中
window3票卖了1张,还剩:3张票
window3卖票中
window2票卖了1张,还剩:2张票
window2卖票中
window3票卖了1张,还剩:1张票
window3卖票中
window2票卖了1张,还剩:0张票
window3今天的票卖完了

我们可以看到,虽然窗口1的机器发生故障了,但是并不影响窗口2和窗口3继续将票卖完。这就是多线程的魅力!

你可能感兴趣的