1. 前言
今天的这篇文章的目的还是为了讲述下什么叫线程,什么是进程。可能之前很多人都是通过
背书
得来的,今天就从通俗易懂的角度来分析下
2. 适合人群
- 线程以及进程的初学者
3. 开始
3.1 什么是程序
- 其实不管是程序/ 进程/ 线程都是基于操作系统而言的。
- 对于操作系统而言的话,程序就是一个后缀为exe或是msi的可执行文件,当我们点击执行文件的时候,会将文件内容加载到操作系统的内存中,同时也是开辟一块空间来保存执行文件
- 程序好比一个js文件,操作系统好比是浏览器。一个执行以及被执行的关系
3.2 什么是进程
先来揭晓下答案:
进度是资源分配的最小单位
其实并不是把执行文件加载到内存总就完事了,而是会安排进程进行资源分配。比如分配端口号,网络等。所以进程是资源分配的最小单位
3.3. 什么是线程
先揭晓答案:
线程是调度执行的最小单位
虽然已经将程序加载到内存中了,同时也是给程序分配资源来,但是并不是靠进程来执行。 其实我们还是靠主线程来执行程序的
所以其实可以理解为线程就是一条执行路径。可能一个事情的完成需要多个线程来完成。这就是所谓的多线程
3.4 QA
解释下面的问题的时候,我们需要知道什么是
CPU密集型处理
。 就是完成功能的大部分处理是需要CPU来完成的,比如计算等。当然IO 相关的不算啊。
3.4.1 单核CPU设置多线程有意义吗
- 在某种程度上是有意义的。
- 场景1:如果用户多个任务都是需要密集型计算的话,那么对于单核CPU而言的话,只能一个一个执行了。因为所有的计算都依赖此唯一的CPU来完成。这种其实多线程没有意义。
- 场景2:同样用户需要完成多个任务,但是一个任务等待IO输入输出的,一个任务是CPU密集型的。这个时候其实一个线程等待外部设备输入交互。另一个线程来进行计算。通过系统控制线程切换来完成。 这种情况下 是存在意义的
3.4.2 一定是线程越多越好吗
我们使用遍历10亿的数字来做一个实验,看看是不是线程开辟越多越好呢
- 通过单线程来执行
- 通过多线程来执行
通过上述实例得知,并不是线程开辟越多越好的。因为线程的切换同样需要时间。但是最合适的办法是经过不断的压测来得出结论才是最真实的
3.4.3 有没有啥公式可以套用呢???
还真有,虽然套用的公式也是前人经过无数次的实验总结的,但是个人还是感觉应该经过自己压测实践最好了。不过公式该给出还是应该给出的
3.5 创建线程的多种方式
class MyThread extends Thread {
@Override
public void run() {
System.out.println("这是创建线程的一种方式:通过继承来实现");
}
}
class MyRun implements Runnable {
@Override
public void run() {
System.out.println("这是创建线程的一种方式:通过实现接口来实现");
}
}
class MyCall implements Callable<String> {
@Override
public String call() throws Exception {
System.out.println("这是创建线程的一种方式:通过实现接口Callable来完成");
return "success";
}
}
public class Thread_02_CreateThread {
@Test
public void test() throws ExecutionException, InterruptedException {
// 线程的创建方式1
new MyThread().start();
// 线程的创建方式2
new Thread(new MyRun()).start();
// 线程的创建方式3
new Thread(() -> {
System.out.println("这是创建线程的一种方式:通过lambda表达式创建");
}).start();
// 线程的创建方式4
FutureTask<String> futureTask = new FutureTask<>(new MyCall());
Thread thread = new Thread(futureTask);
thread.start();
System.out.println(futureTask.get());
// 线程的创建方式 5
ExecutorService executorService = Executors.newCachedThreadPool();
executorService.execute(() -> {
System.out.println("这是创建线程的一种方式:通过线程池来进行创建");
});
Future<String> submit = executorService.submit(new MyCall());
System.out.println(submit.get());
executorService.shutdown();
}
上述代码是Java中创建线程的几种方式
3.5.1 继承Thread
跟 Runnable
哪个好呢???
- 总体而言的话是
Runnable
会更好点。因为在Java中是单继承,多实现。如果我们开发中继承了Thread
就不能继承别的类的。但是我们可以实现多个接口- 可能唯一有遗憾的就是 这些继承或是接口 都是没有返回值的
3.5.2 如果想要返回值呢???
如果想线程有返回值的话,可以继承接口
Callable
来指定返回值
3.5.3 如果想写法简单点呢???
如果只是想在线程内做一些操作的话,对返回值无要求,同时想要写法简单点,可以使用上述代码中的lambda来完成线程的创建
4. 结束
以上是对程序/ 线程/ 进程的理解。以及在Java中创建线程的几种方式。源码请参照. 如果大家觉得对自己有用处的话,希望大家点赞,收藏。多多关注小编哦