Thread源码分析

如上图,可见:RUNNABLE = 正在JVM中运行的(Running)+ 可能在等待操作系统级别的资源(Ready),例如CPU时间片

  线程创建之后,不会立即进入就绪状态,因为线程的运行需要一些条件(比如内存资源),只有线程运行需要的所有条件满足了,才进入就绪状态。

  当线程进入就绪状态后,不代表立刻就能获取CPU执行时间,也许此时CPU正在执行其他的事情,因此它要等待。当得到CPU执行时间之后,线程便真正进入运行状态。

  线程在运行状态过程中,可能有多个原因导致当前线程不继续运行下去,比如用户主动让线程睡眠(睡眠一定的时间之后再重新执行)、用户主动让线程等待,或者被同步块给阻塞,此时就对应着多个状态:time waiting(睡眠或等待一定的事件)、waiting(等待被唤醒)、blocked(阻塞)。

  当由于突然中断或者子任务执行完毕,线程就会被消亡。

三.Thread类中的方法

老规矩,先看源码注释:

+ View Code

  Thread类实现了Runnable接口,在Thread类中,

  关键属性

扫描二维码关注公众号,回复: 6018923 查看本文章

  name是表示Thread的名字,可以通过Thread类的构造器中的参数来指定线程名字,

  priority表示线程的优先级(最大值为10,最小值为1,默认值为5),

  daemon表示线程是否是守护线程,如果在main线程中创建了一个守护线程,当main方法运行完毕之后,守护线程也会随着消亡。在JVM中,垃圾收集器线程就是守护线程。

  target表示要执行的任务。

  group线程群组

  关键方法

  以下是关系到线程运行状态的几个方法:

  1)start

  start()用来启动一个线程,当调用start方法后,系统才会开启一个新的线程来执行用户定义的子任务,在这个过程中,会为相应的线程分配需要的资源。

  2)run

  run()方法是不需要用户来调用的,当通过start方法启动一个线程之后,当线程获得了CPU执行时间,便进入run方法体去执行具体的任务。注意,继承Thread类必须重写run方法,在run方法中定义具体要执行的任务。

  3)sleep

  sleep方法有两个重载版本:

sleep让线程睡眠,交出CPU,让CPU去执行其他的任务。sleep方法不会释放锁,也就是说如果当前线程持有对某个对象的锁,则即使调用sleep方法,其他线程也无法访问这个对象。sleep方法相当于让线程进入阻塞状态。

  4)yield

  调用yield方法会让当前线程交出CPU权限,让CPU去执行其他的线程。它跟sleep方法类似,同样不会释放锁。但是yield不能控制具体的交出CPU的时间,另外,yield方法只能让拥有相同优先级的线程有获取CPU执行时间的机会。

  注意,调用yield方法并不会让线程进入阻塞状态,而是让线程重回就绪状态,它只需要等待重新获取CPU执行时间,这一点是和sleep方法不一样的。

  5)join

  join方法有三个重载版本:

 可以看出,当调用thread.join()方法后,main线程会进入等待,然后等待thread执行完之后再继续执行。

  实际上调用join方法是调用了Object的wait方法,这个可以通过查看源码得知:

wait方法会让线程进入阻塞状态,并且会释放线程占有的锁,并交出CPU执行权限。

  6)interrupt

  interrupt,中断。单独调用interrupt方法可以使得处于阻塞状态的线程抛出一个异常,也就说,它可以用来中断一个正处于阻塞状态的线程;

  7)stop

  stop方法已经是一个废弃的方法,它是一个不安全的方法。因为调用stop方法会直接终止run方法的调用,并且会抛出一个ThreadDeath错误,如果线程持有某个对象锁的话,会完全释放锁,导致对象状态不一致。所以stop方法基本是不会被用到的。

  8)destroy

  destroy方法也是废弃的方法。基本不会被使用到。

猜你喜欢

转载自blog.csdn.net/u010310183/article/details/84399095