线程的本质

线程是操作系统调度的最小单位,用于提高程序的实时性。线程通过Thread、Runnable或Callable接口创建,线程池进行管理。线程状态包括新建、就绪、运行、阻塞和死亡。线程间通信涉及join、wait/notify、sleep等方法,中断线程推荐使用interrupt而非stop。线程上下文切换涉及CPU状态保存与恢复,可能导致性能开销。守护线程优先级低,用于服务用户线程。

线程的本质

是什么

线程是操作系统能够进行运算调度的最小单位

注:并发-》交替,并行-》同时

为什么出现

在一个应用进程中,会存在多个同时执行的任务,如果其中一个任务被阻塞,将会引起不依赖该任务的任务也被阻塞。通过对不同任务创 建不同的线程去处理,可以提升程序处理的实时性

怎么使用

  1. 继承Thread  
  2. 实现Runnable接口
  3. 实现Callable接口  通过拿到Future(Future提供了3种功能:(1)能够中断执行中的任务(2)判断任务是否执行完成(3)获取任务执行完成后额结果。)接口对象或FutureTaskd(实现了继承Runnable和Future接口的RunnableFuture接口)对象,了解任务执行情况。FuturnTask与Future的区别
  4. 线程池创建

注意:可以通过ExecuteService(线程池有关),Callable,Future实现带有返回值的多线程

    区别:

  1. 优:访问当前线程直接this     缺:不能继承其他类
  2. 优:可以继承其他的类。在这种方式下,可以多个线程共享同一个目标对象,所以非常适合多个相同线程来处理同一份资源的情况,从而可以将CPU代码和数据分开,形成清晰的模型,较好地体现了面向对象的思想      缺:访问当前线程使用Thread.currentThread()
  3. 优:任务执行后可返回值,前两种方法没有,且call()有异常抛出,run()没有。运行Callable任务可以拿到一个Future对象,表示异步计算的结果。它提供了检查计算是否完成的方法,以等待计算的完成,并检索计算的结果。通过Future对象可以了解任务执行情况,可取消任务的执行,还可获取执行结果

使用场景

  • 文件下载
  • 后台任务
  • 异步处理:如记录日记
  • 多步骤任务处理

生命周期

线程的5种状态:新建(New),就绪(Runnable),运行(Running),阻塞(Blocked),死亡(Dead)

    线程变化的状态转换图例如以下:

      1)新建状态(New):新创建了一个线程对象。

      2)就绪状态(Runnable):线程对象创建后,其它线程调用了该对象的start()方法。该状态的线程位于可执行线程池中,变得可执行,等待获取CPU的使用权。

      3)执行状态(Running):就绪状态的线程获取了CPU。执行程序代码。

      4)堵塞状态(Blocked):堵塞状态是线程由于某种原因放弃CPU使用权。临时停止执行。直到线程进入就绪状态,才有机会转到执行状态。

        堵塞的情况分三种:

          (一)等待堵塞:执行的线程执行wait()方法,JVM会把该线程放入等待池中。

          (二)同步堵塞:执行的线程在获取对象的同步锁时,若该同步锁被别的线程占用。则JVM会把该线程放入锁池中。

          (三)其它堵塞:执行的线程执行sleep()或join()方法,或者发出了I/O请求时。JVM会把该线程置为堵塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完成时。线程又一次转入就绪状态。

      5)死亡状态(Dead):线程运行完了或者因异常退出了run()方法,该线程结束生命周期。

补充:

线程启动-》start方法底层是针对不同操作系统实现不同线程创建和启动。可以下载hospot源码看

守护线程

优先级低,为用户线程提供服务,在start()之前可通过SetDaemon(true)设置守护线程,守护线程中产生的新线程也是守护线程,其生命周期依赖于系统,不依赖终端

线程中断【回过头看了一下,感觉其中Thread.currentThread().isInterrupted()和Thread.isInterrupted()区别他估计是打错了,应该是Thread.currentThread().isInterrupted()和Thread.interrupted()】(注意三个方法interrupt()(告诉线程中断,park--unpark),isInterrupted()(判断线程中断标志,并复位),interrupted()(对设置中断标识的线程复位,当阻塞线程中断抛出InterruptedException但线程还是会继续运行))

(1)使用退出标志,使线程正常退出,也就是当 run 方法完成 后线程终止。

(2)通过 return 退出 run 方法

(3)通过对有些状态中断抛异常退出 thread.interrupt() 中断。

(4)使用 stop 方法强行终止线程(过期)

线程上下文切换

上下文切换可以认为是内核(操作系统的核心)在 CPU 上对于进程(包括线程)进行切换,上下 文切换过程中的信息是保存在进程控制块(PCB, process control block)中的。PCB还经常被称 作“切换桢”(switchframe)。信息会一直保存到CPU的内存中,直到他们被再次使用。 

1. 挂起一个进程,将这个进程在 CPU 中的状态(上下文)存储于内存中的某处。

2. 在内存中检索下一个进程的上下文并将其在 CPU 的寄存器中恢复。

3. 跳转到程序计数器所指向的位置(即跳转到进程被中断时的代码行),以恢复该进程在程序中。

线程中方法解释

1. 

  • join(),本质是是wait/notifyall,用于在某一个线程的执行过程中调用另一个线程执行,等到被调用的线程执 行结束后,再继续执行当前线程
  • wait/notifyall,互斥的,通过synchronized来使用,不然可能死锁

2. sleep(),使线程暂停执行一段时间,直到等待的时间结束才恢复执行或在这段时间内被中断

  • 工作流程为:挂起线程并修改其运行状态
  • 用sleep()提供的参数来设置一个定时器。
  • 当时间结束,定时器会触发,内核收到中断后修改线程的运行状态。 例如线程会被标志为就绪而进入就绪队列等待调度
  • 注:sleep(0)的意义:抢到cpu的线程回到抢占cpu的队列,重新计算优先级,竞争cpu

sleep和wait区别

1、这两个方法来自不同的类分别是Thread和Object
2、最主要是sleep方法没有释放属锁,而wait方法释放了锁,使得其他线程可以使用同步控制块或者方法。
3、wait,notify和notifyAll只能在同步控制方法或者同步控制块里面使用,而sleep可以在任何地方使用(使用范围)
4、sleep必须捕获异常,而wait,notify和notifyAll不需要捕获异常
5、sleep是Thread类的静态方法。sleep的作用是让线程休眠制定的时间,在时间到达时恢复,也就是说sleep将在接到时间到达事件事恢复线程执行。wait是Object的方法,也就是说可以对任意一个对象调用wait方法,调用wait方法将会将调用者的线程挂起,直到其他线程调用同一个对象的notify方法才会重新激活调用者。

stop()方法(不使用)

作为一种粗暴的线程终止行为,在线程终止之前没有对其做任何的清除操作,因此具有固有的不安全性。 用Thread.stop()方法来终止线程将会释放该线程对象已经锁定的所有监视器。如果以前受这些监视器保护的任何对象都处于不连贯状态,那么损坏的对象对其他线程可见,这有可能导致不安全的操作。 由于上述原因,因此不应该使用stop()方法,而应该在自己的Thread类中置入一个标志,用于控制目标线程是活动还是停止。如果该标志指示它要停止运行,可使其结束run()方法。如果目标线程等待很长时间,则应使用interrupt()方法来中断该等待。

interrupt方法(重点,自己百度了解)

是stop()的替代,当其他线程通过调用当前线程的interrupt方法,表示向当前线程打个招呼,告 诉他可以中断线程的执行了,至于什么时候中断,取决于当前线程自己,Thread.interrupted()对设置中断标识的线程复位,并且返回当前的中断状态

suspend()/resume()方法(不使用)

该方法已经遭到反对,因为它具有固有的死锁倾向。调用suspend()方法的时候,目标线程会停下来。如果目标线程挂起时在保护关键系统资源的监视器上保持有锁,则在目标线程重新开始以前,其他线程都不能访问该资源。除非被挂起的线程恢复运行。对任何其他线程来说,如果想恢复目标线程,同时又试图使用任何一个锁定的资源,就会造成死锁。由于上述原因,因此不应该使用suspend()方法,而应在自己的thread类中置入一个标志,用于控制线程是活动还是挂起。如果标志指出线程应该挂起,那么用wait()方法命令其进入等待状态。如果标志指出线程应当恢复,那么用notify()方法重新启动线程。resume()是继续执行

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值