多线程程序好处就是可以提高cpu使用率和系统的性能。这里举个例子,民以食为天,咱们以餐馆为例(后面基本上都用餐馆作为对象),后面如果没有特殊说明均采用本节相关术语,围绕餐馆我们可以抽象出如下几个角色以及线程映射:
No. | 角色 | 线程 | 属性 | 耗时(Unit:s) |
1 | 老板(管理) | 主线程 | 服务方 | - |
2 | 厨师(做菜) | 子线程 | 服务方 | 60 |
3 | 服务员(上菜) | 子线程 | 服务方 | 30(单趟) |
4 | 采购员(食材) | 子线程 | 服务方 | - |
5 | 食客 | 线程 | 请求方 | - |
下面咱们来下一个单线程(只有主线程)的例子,假设有2位食客,餐馆只提供一个番茄炒蛋,厨师完成番茄炒蛋的时间是60s,上菜的时间是30s,按照理论情况下,单线程情况下2位客人被服务的时间合计60s+2*30s+60s+30s = 210s,如果使用二个线程(厨师+服务员)时间就是2*60s = 120ms(因为厨师炒菜60s,然后服务员从上菜到下一个食客上菜耗时30s)。
public class Test {
public static void main(String[] args) {
doSingleThread();//单线程执行
doMultiThread();//多线程执行
}
private static void doSingleThread() {
long t1 = System.currentTimeMillis() / 1000;
Chef.cook();
Waiter.go();
Waiter.back();
Chef.cook();
Waiter.go();
long t2 = System.currentTimeMillis() / 1000;
System.out.println("【单线程】为两位食客供餐完成,耗时:" + (t2 - t1) + "s.");
}
private static void doMultiThread() {
long t1 = System.currentTimeMillis() / 1000;
Thread chefThread = new Thread(() -> {
Chef.cook();
Chef.cook();
}, "厨师");
Thread waiterThread = new Thread(() -> {
Waiter.go();
Waiter.back();
Waiter.go();
}, "服务员");
chefThread.start();
waiterThread.start();
try {
chefThread.join();
waiterThread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
long t2 = System.currentTimeMillis() / 1000;
System.out.println("【多线程】为两位食客供餐完成,耗时:" + (t2 - t1) + "s.");
}
private static class Chef {
public static void cook() {
try {
TimeUnit.SECONDS.sleep(60);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
private static class Waiter {
public static void go() {
try {
TimeUnit.SECONDS.sleep(30);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static void back() {
try {
TimeUnit.SECONDS.sleep(30);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
打印的耗时结果:
【单线程】为两位食客供餐完成,耗时:210s.
【多线程】为两位食客供餐完成,耗时:120s.
通过以上程序实例,我们可以明白如下几个问题:
1. 什么情况下使用多线程?
我们都知道一个任务可以分多个步骤,如果一个任务的多个步骤可以独立出来执行并不会对执行结果产生影响,我们可以采用多线程。
2. 多线程能给我带来什么好处?
由于采用多线程可以减少cpu由于在单线程情况下由于任务某个步骤的阻塞或者等待导致的cpu的空闲,提高了cpu利用率,这样并发的执行,就会带来程序性能的提升。上面例子,
程序执行时间节省出来的就是服务员(原来厨师)在上菜过程中的耗时,我们可以看出如果采用多线程其实程序的耗时大部分(还有上下文切换耗时等)取决于耗时最长的那个步骤。