多线程总结知识点一

多线程知识点总结

1、什么是进程?

进程是具有一定功能的程序在一个数据集上的一次动态执行的过程,进程是操作系统进行资源分配和调度的一个独立单位,是程序运行的载体。

2、什么是线程?

**线程是操作系统能够进行运算调度的最小单位。**他被包含在进程当中,是进程当中的实际运作单位。一条线程就是指在进程中单一的处理流程,一个进程可以由主线程来启动多个子线程线程,每一条线程可以执行不同的任务。

3、进程和线程的区别?

进程和线程的主要差别在于它们在操作系统中资源管理方式的不同。

进程有独立的地址空间,一个进程崩掉后,在操作系统的保护模式下不会对其他进程产生影响。

线程只是进程中的不同的执行路径。线程有自己的堆栈和局部变量,但是线程之间没有独立的地址空间,对于多个线程的协作共同完成任务的进程来说,一个线程的死掉,就会导致其他线程也会收到影响,从而等于 一个线程的死掉等于整个进程死掉,所以说多线程程序健壮性没有多进程程序的好,但是多进程程序在对进程 切换时,耗费的资源较大,效率要差一些。

对于一些要求同时进行并且又要共享谋陷变量的并发操作,只能用多线程,而不能用进程。

4、多线程和单线程有什么区别?

单线程程序:程序执行时,就只有一条执行路径,也就是说程序执行过程中只有一个有效的操作序列,不同的操作之间都会有明确的执行先后的顺序,容易出现代码阻塞。

在java的main()中,如果没有添加多线程的对象并启动的话,那么这个程序执行的时候就只有一个线程,也就是主线程main,而在main中的动作(操作)就只能从上往下一次执行,容易造成代码阻塞。

多线程程序:有多个线程,线程间能独立运行,能有效的避免代码阻塞问题,并且能有效的提高程序的运行性能。

比如一个人的对象,他有跑的方法和听音乐的方法。这两个动作可以单独的做,也可以并行的做。如果想要并行的做的话那么就只能在多线程的情况下进行。也就是说一个线程在听音乐,一个线程在跑步,谁也不影响谁。

又或者一道工序,需要分成多个阶段去完成,这些阶段互不依赖,如果在一个线程的环境下它只能一个阶段一个阶段的去完成;在多线程的程序下可以在同一时间,去执行各个阶段,这样一来就有效提高了程序的运行性能和效率。

5、为什么要是用多线程?

  • 使用多线程可以减少程序响应时间。

在单线程的情况下,某个程序很耗时或者陷入长时间等待(如等待网络响应),此时程序将不会去响应鼠标和键盘操作,使用多线程后,可以吧这个耗时的代码分到一个单独的线程中取执行,从而程序就具备了更好的交互。

  • 与进程相比,线程的创建和切换开销更小。

由于启动一个新的进程必须给这个进程分配独立的地址空间,建立许多数据结构来维护线程代码段、数据段等信息,而运行于同一个进程内的线程共享代码段、数据段,线程的启动或切换的开销就比进程要少很多。

  • 多CPU或多核心计算机本身就具有执行多线程的能力。

如果单个线程,将无法重复利用计算机资源,造成资源的巨大浪费。在多CPU计算机上使用多线程能提高CPU的利用率。

  • 使用多线程可以简化程序结构,使用程序便于理解和维护。

一个复杂的进程可以差分成多个线程来执行。

6、什么是线程安全?

当在进程中的共享内存中有一些共享的变量或数据和一些共享对象,当多个线程去访问,不考虑这些线程在运行时环境和交替运行,也不需要其他的同步和在调用方进行任何的调整操作,多线程在任何时候对这些数据,变量和对象的操作度可以获取到争取的结果,那么这个数据、变量、对象时线程安全的。

——<<深入Java虚拟机>>

7、为什么要是用线程同步?

Java允许多线程并发控制,当多个线程同时操作一个可共享的资源变量时(如数据的增删改查),将会导致数据不准确。相互之间相互产生冲突。

因此需要加入同步锁以避免在该线程在没有完成操作之前,不能被其他线程调用,从而保证了该变量的唯一性好准确性。

8、如何确保线程安全?

  • 对非安全的代码进行枷锁控制
  • 使用线程安全的类
  • 多线程并发的情况下,线程共享的变量改为方法级的局部变量。

9、Java内存模型是什么?

Java中所有变量都是存储在主存中的,对于所有线程都是共享的(因为在同一线程中),每一个线程都有自己的工作内存或者本地内存(Working Memory)工作内存中保存的是该线程所需要的一些变量(是主内存中的一些变量副本),线程之间无法直接相互访问,变量传递均需要通过主存去完成,但是在程序内部可以相互调用(通过对象方法),所有的线程之间的通信就是这样简单,速度也很快。

多线程之间的交互如图:A线程往B线程消息传递

image-20230419141431020

从上图可以看出来线程拥有自己的堆栈,它们之间是没有单独的内存空间的。

进程间的内部数据和状态都是完全相对独立的,因此进程间的通信大多数情况下都是通过网络编程来实现。线程本身的数据,通常只有寄存器数据,以及一个程序执行时使用的堆栈,所以线程的切换的负担要比进程的小。

CPU对线程的调度是随机(分时调度),在Java程序中,JVM负责线程的调度。线程调度是指按照特定的机制(通常使用时间片轮询算法)为多个线程分配CPU的使用权。也就是说,实际执行的不是进程,而是线程,因此CPU调度的最小是线程,二资源分配与管理的最小单位是进程。

10、Java中对和栈有什么不同?

在函数定义的基本类型对象的引用变量都是在函数的栈内存中分配。

堆:堆内存用于存放由new创建出来的对象和数组

更通俗的说:堆是用来存放对象的,栈是用来存放执行程序的。

11、JVM中哪一个参数是用来控制线程的堆栈大小的?

-Xss:参数用来控制线程的堆大小。

12、什么是竞态条件?如何发现和解决竞争?

当主存中存在临界资源,如果在多线程的运行时环境下,该资源对多线程的执行顺序敏感,即是线程的不同执行顺序会导致结果额错误,这就是存在静态条件。

在临界区中使用相关的线程同步(互斥)就可以避免金泰条件。

界区的实现方法常见的有两种:一种是Synchronized,一种是用Lock显示锁实现。

13、线程安全的级别有?

  • 不可变:不可变的对象一定是线程安全的,并且永远都不需要额外的同步操作。

​ Java类库中大多数基本数值类型如Integer、String和BigInteger都是不可变的。

  • 有条件的线程安全:有条件的线程安全类对于单独的操作可以是线程安全的,但是某些操作序列可能需要额外的同步。

​ 有条件的线程安全例子是遍历由HashTable或者Vector返回的迭代器。

  • 无条件的线程安全:由类的规格说明所规定的约束的对象被多个线程访问时任然有效,不管线程的运行时环境如何排列,线程都不需要要做任何的同步。

​ 如Random、ConcurrentHashMap、Concurrent集合、atomic

  • 非线程安全(安全兼容):线程兼容类不是线程安全的,但是可以通过正确的使用同步而在并发环境中安全的使用。

    ​ 如ArrayList

  • 线程对立:线程对立是那些不管是否采用了同步措施,都不能在多线程环境下并发使用的代码。

14、你对线程的优先级的理解是什么?

每一个线程对象都是有一个默认的优先级,缺省值为5.线程优先级的范围是(1~10),优先级越高就更加的容易获得CPU的执行权,注意,并不是高的优先级就一定会比低优先级的线程先执行。这依赖于线程调度的实现,这个实现时和操作系统相关的。

15、什么是原子操作?

所谓原子操作,就是在一组下不可被中断的操作的,要么全部成功,要么全部执行失败,不会出现部分成功的情况。如检查数值,改变数值,以及可能发生的睡眠操作均是单一的,不可分割的原子操作完成。不可能以出现部分完成,部分成功等缺失情况。简单说”要么成,要么败“,这就是原子操作的特性。

16、什么是线程调度器(Thread Scheduler)和时间分片(Time Slicing)?

线程调度器是一种操作系统服务,它负责对处于就绪状态(Runnable)的线程分配CPU时间,一旦常见一个线程并且启动它,那么它的执行便依赖于线程调度器的实现。

时间分片就是指将CPU的可用时间分配给Runnable状态的线程的过程,分配CPU时间可以基于线程的优先级或者线程的等待时间。

线程的调度不受到Java虚拟机的控制,所以应由应用程序来控制它是一种不就错得选择。

时间片与时间分片不同:时间片是指线程在CPU中执行的时间,而时间分片是指在为线程分配CPU的可用时间。

17、在多线程中,什么是上下文切换(context-switching)?

单核CPU也支持多线程执行代码,CPU通过给每一个线程分配CPU时间片来实现这个机制。时间片是CPU分配给各个线程的时间,因为时间片非常短,所以CPU不断的切换线程来执行,让我们错觉的以为多线程在同一时间执行的,一般时间片是几十毫秒。

操纵系统中,CPU的时间分片切换到拎一个就绪的线程,需要保存当前线程的运行位置和一些数据(也称保护现场),同时恢复需要运行的线程环境信息。

18、用户线程和守护线程有什么区别?

守护线程相当于是一个服务线程,比如典型的服务线程垃圾回收机制线程。守护线程都是为JVM中所有非守护线程 提供便利服务

只要JVM虚拟机中,还有一个非守护线程还没有结束,全部守护线程就会一直工作;只有当最后一个非守护线程结束是,守护线程会随着JVM一同结束工作。

用户线程和守护线程几乎没有什么区别:唯一的区别就在于虚拟机的离开:如果用户线程已经全部退出虚拟机了,只剩下守护线程Daemon Thread的存在了,虚拟机也就退出了。

没了用户线程(被守护者)需要守护了,用户线程(守护者)也没必要存在。

19、如何守护线程?以及在什么场合来使用它?

任何用户线程都可以设置为守护线程,前提是在线程start()前,调用setDaemon(Boolean flag),参数为true设置为守护线程,否则会出现异常。线程默认为用户线程。

守护进程相当于后台管理者。

比如:进行垃圾回收,垃圾清理等工作。

20、线程状态的转换?

  1. 新生状态(New):新建了一个线程对象,未调用start()。

  2. 就绪状态(Runnable):线程对象创建以后,其他线程(主线程)调用了该对象的start()方法。该状态的线程就会进入 可运行线程池中,变得可运行,等待获得CPU使用权。

  3. 运行状态(Running):位于可运行线程池中的线程 获得了CPU,执行代码。

  4. 阻塞状态(Blocked):阻塞状态的出现是正在执行的线程由于某种原因放弃了CPU使用权,暂时停止运行。直到线程进入就绪状态,才有机会转入到运行状态。

    ​ 阻塞的情况分为三种:

    1. ​ 等待阻塞:运行的线程执行wait()的方法,JVM会把该线程放入等待池中。
    2. 同步阻塞:运行的线程在获取某对象的同步锁时,若该线程的同步锁被别的线程占用,则JVM会把该线程放入锁池中。
    3. 其他阻塞:运行时的线程执行sleep()或join()方法,又或者发出了IO请求时,JVM也会把该线程设置为阻塞状态。当sleep()状态超时,join()等待线程终止或者超时,或者IO处理完毕是,线程重新进入就绪状态。(sleep():不会释放持有的锁)
  5. 死亡状态(Dead):线程执行完毕或者因异常退出了run()方法,该线程生命周期结束。

image-20230412210446972

21、线程中断是否能直接使用stop()?

Java提供的终止方法只有一个stop,不建议使用此方法。

  1. stop()方法是过时了的,从Java编码规则来说过时的方式不建议使用。
  2. stop()方法会导致代码逻辑不完整,这是很危险的。比如该线程正在保存数据,你突然build一枪把它打死了,数据没保存完成,这就很危险。
    yj-1681892965362)]

21、线程中断是否能直接使用stop()?

Java提供的终止方法只有一个stop,不建议使用此方法。

  1. stop()方法是过时了的,从Java编码规则来说过时的方式不建议使用。
  2. stop()方法会导致代码逻辑不完整,这是很危险的。比如该线程正在保存数据,你突然build一枪把它打死了,数据没保存完成,这就很危险。

这是简单基础部分,过几天会更新更难一点的问题,加油!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

明天码上有钱啦

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值