发布于2020-11-19 20:49 阅读(968) 评论(0) 点赞(2) 收藏(2)
解释线程和进程比较枯燥的概念就是:进程是资源分配的基本单位,线程是CPU的调度的最小单位。这样的答案都太字面,抽象不太容易让人理解,所以我还是举一个曾经看到过的例子:
如果说进程是一列拉载着数据信息的火车,那么线程就是一节一节的车厢。
就像火车可以拥有多节车厢一样,一个进程可以拥有多个线程。
如果一列火车发生了故障,很多情况下是不会影响到其他的火车的运行,或者说影响的范围有限。而当一节车厢发生故障的时候,这列火车就很难再继续运行。这样就很好理解一个进程奔溃后,在保护模式下对其他进程的影响是有限的,但如果是一个线程挂掉了,进程很大概率下都会崩溃。所以多进程要比多线程更加的健壮
如果理解了什么是线程,什么是进程,那么两者之间都有哪些区别呢?
首先总结性的比较一下线程和进程:进程和线程都是CPU工作时间段的描述,是运行中的程序指令的一种描述,但是各自的粒度不同。
注意:以下大篇概念出没,如有困倦请跳过。
首先我们先看一个程序运行的背景
我们电脑其实就是通过CPU+RAM(内存)+外设(如显卡,光驱等)组成,一个程序的实际运行实际上就是通过CPU+RAM的组合处理的。
这里面有一个不能够被忽略的事实就是CPU中的运算单元太快了,在[计算机原理]–CPU的基础入门中我提到过ALU(运算单元)的运算能力是远大于寄存器的。更何谈缓存区和RAM。那么当多个任务需要执行怎么办?难道需要执行完第一个任务然后再去执行第二个任务?如果这样的话,CPU实际运行的时间其实和等待的时间是有着数量级的差异。如果还是不懂得话,可以理解为我们上学时期在写作业的时候,由于往作业本上写字的速度是跟不上大脑计算的速度的,当我们大脑已经计算出1+1=2的时候,可能手刚刚写完加号,而此刻大脑中负责运算的部位已经开始休息等待下一次的运算。运算可能需要1ms,而写字需要整整1s。
还有一个需要知道的事实:执行一段程序代码,实现一个功能的过程中,当得到CPU的时候,相关的资源必须已经就位,等待电脑通过调度算法决定哪个任务需要CPU来执行,此时PC(指令计数器)指向该段任务代码,CPU获取指令开始执行。
那么串联起来其实就是:CPU调取进程A,获取其中的指令,开始执行A,保存A的结果(上下文,这里不做赘述)。然后调入下一个等待执行的进程B,开始执行B。 当然如果CPU分配给程序B的时间片用完了,那么他就会暂时的将运行结果保存在上下文中,备切换出去,等待CPU的再次临幸。
背景叙述完了,那么什么是进程和线程呢?
进程就是CPU上下文切换之间的程序执行的部分,是此刻在CPU中运行程序的描述。也可以说是CPU执行时间的描述。
那么线程呢?
进程的颗粒度太大了,每次执行都要进行上下文切换。如果我们把一个软件当做是一个应用程序,那么一个软件的执行不可能只有一条逻辑组成的,必须有多个程序段的分支来实现。那么当我们运行程序时就变成了程序A的a小段代码快获得了CPU的使用权,此时CPU加载a小段的指令,开始执行a小段。当a小段执行完毕后再切换到b小段的指令执行。最后当所有代码段执行完毕后,保存程序A的运算结果,退出程序A,开始执行程序B。在这里,程序A与程序B之间的切换时间远大于代码段a与代码段b之间的切换。而代码单a和代码段b的时间总和就是程序A的运行时间。这里的代码段a,b其实就是线程,他共享了进程A的上下文环境,描述了CPU在更加细小的时间段内完成的任务。
到此不难理解,进程就是对CPU处理在一个时间段内工作状态的描述,而线程则是这段时间状态内每一条详细工作内容的描述,本质上进程和线程的区别就是对于CPU工作时间段描述的颗粒度不同。
区别于用户线程,守护线程指的是程序运行的时候在后台提供辅助服务的一些线程。我们常说的GC线程(垃圾回收线程)就是典型的守护线程。守护线程的特点就是当JVM发现没有任何业务线程的时候就会离开,守护线程也随之终止。在Java中,守护线程的实现也很简单,直接调用Thread对象的setDaemon(true)就可以。在使用守护线程的时候要注意一下三点:
在java中,我们常说的生命周期可以大概分为:
具体的线程生命周期的切换可以参考下图
在jdk官方文档中,提到了线程的创建方式有两种:
public class TheadDemo extends Thread {
@Override
public void run() {
System.out.println("集成Thread类");
}
}
public class ThreadDemo02 implements Runnable {
@Override
public void run() {
System.out.println("实现runnable接口");
}
}
1) 为什么一个线程不能够两次调用start()?
Java的线程是不允许启动两次的,第二次调用必然会抛出IllegalThreadStateException,这是一种运行时异常,多次调用start被认为是编程错误。
2) start()和run()这两个方法有什么区别?
// 新建线程
public class TheadDemo extends Thread {
@Override
public void run() {
println("开始执行run方法体,此时时间为:"+new Date());
try {
Thread.currentThread().sleep(1000l*10);
String name = Thread.currentThread().getName();
System.err.println("当前线程:"+name+"执行结束");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private static void println(String message) {
System.out.println(message);
}
}
public static void main(String[] args) throws InterruptedException {
TheadDemo theadDemo = new TheadDemo();
theadDemo.start();
System.err.println("主流程继续运行,此时时间为:"+new Date());
TheadDemo theadDemo2 = new TheadDemo();
theadDemo2.run();
System.err.println("主流程继续运行,此时时间为:"+new Date());
}
原文链接:https://blog.csdn.net/xiaoai1994/article/details/109736302
作者:java之恋
链接:http://www.javaheidong.com/blog/article/1009/79780a16eeef6700e795/
来源:java黑洞网
任何形式的转载都请注明出处,如有侵权 一经发现 必将追究其法律责任
昵称:
评论内容:(最多支持255个字符)
---无人问津也好,技不如人也罢,你都要试着安静下来,去做自己该做的事,而不是让内心的烦躁、焦虑,坏掉你本来就不多的热情和定力
Copyright © 2018-2021 java黑洞网 All Rights Reserved 版权所有,并保留所有权利。京ICP备18063182号-2
投诉与举报,广告合作请联系vgs_info@163.com或QQ3083709327
免责声明:网站文章均由用户上传,仅供读者学习交流使用,禁止用做商业用途。若文章涉及色情,反动,侵权等违法信息,请向我们举报,一经核实我们会立即删除!