方法名 | static | 功能说明 | 注意要点 |
start() | 启动一个新线程,在新的线程中运行run方法 | start()只是让线程进入就绪状态,能否运行取决于cpu时间片什么时候分配给这个线程,只能调用一次,多次调用会报异常
IllegalThreadStateException
| |
run() | 新线程启动后调用的业务逻辑代码 | 可以通过Thread调用Runnable参数实现Runnable的run方法,也可以创建Thread子类来覆盖重写,此方法默认不执行任何操作 | |
join() | 等待线程执行结束 | ||
join(long n) | 最多等待n毫秒,线程还未结束则执行下一行代码 | ||
getId() | 获取线程型的id | id唯一 | |
getName() | 获取线程名 | ||
setName(String)
|
修改线程名
| ||
getPriority()
|
获取线程优先级
| ||
setPriority(int)
|
修改线程优先级
|
java
中规定线程优先级是
1~10
的整数,较大的优先级
能提高该线程被
CPU
调度的机率
| |
getState()
|
获取线程状态
|
Java
中线程状态是用
6
个
enum
表示,分别为:
NEW, RUNNABLE, BLOCKED, WAITING,
TIMED_WAITING(操作系统少这一个), TERMINATED
| |
isInterrupted()
|
判断是否被打
断,打断状态为true,为打断为false
|
不会清除
打断标记
(如果flag是true,使用这个方法不会更改flag)
| |
isAlive()
|
线程是否存活
(还没有运行完
毕)
| ||
interrupt()
|
打断线程
|
如果被打断线程正在
sleep
,
wait
,
join
会导致被打断
的线程抛出
InterruptedException
,并清除
打断标
记
;如果打断的正在运行的线程,则会设置
打断标
记
;
park
的线程被打断,也会设置
打断标记
| |
interrupted()
|
static
|
判断当前线程是
否被打断
|
会清除
打断标记
|
currentThread()
| static |
获取当前正在执
行的线程
| |
sleep(long n)
|
static
|
让当前执行的线
程休眠
n
毫秒,
休眠时让出
cpu
的时间片给其它
线程
| |
yield()
|
static
|
提示线程调度器
让出当前线程对
CPU
的使用
|
主要是为了测试和调试
|
1.start 与 run
直接调用 run 是在主线程(main方法)中执行了 run,
没有启动新的线程
使用 start
是启动新的线程,通过新的线程间接执行 run 中的代码
2.sleep 与 yield
sleep
1. 调用 sleep 会让当前线程从 Running 进入 Timed Waiting 状态(阻塞)
2. 其它线程可以使用 interrupt 方法打断正在睡眠的线程,这时 sleep 方法会抛出 InterruptedException
3. 睡眠结束后的线程未必会立刻得到执行
4. 建议用 TimeUnit 的 sleep 代替 Thread 的 sleep 来获得更好的可读性
(sleep不会释放锁,waith会释放锁,因此sleep时间结束后会等待CPU时间片轮转过来立即执行而wait结束后需要先竞争锁,竞争锁后再等待CPU时间片分配给它才执行)
yield
1.
调用
yield
会让当前线程从
Running
进入
Runnable
就绪状态,然后调度执行其它线程
2.
具体的实现依赖于操作系统的任务调度器
(yield将线程由运行状态转变为就绪状态,所以有可能线程刚调用yield变为就绪状态就又被cpu调用这个线程)
3.getPriority()
线程优先级
线程优先级会提示(
hint
)调度器优先调度该线程,但它仅仅是一个提示,调度器可以忽略它
如果
cpu
比较忙,那么优先级高的线程会获得更多的时间片,但
cpu
闲时,优先级几乎没作用
4.join
线程执行结束会导致 join 结束 等待线程执行完成
5.interrupt
打断
sleep
,
wait
,
join 的线程
会清空打断状态
打断正常运行的线程
,
不会清空打断状态
(打断状态就是一个boolean类型的值,用来判断是否正常打断)
打断
park
线程
,
不会清空打断状态
6.park/unpark
//暂停当前线程
LockSupport.park();
//恢复某个线程的运行
/LockSupport.unpark(暂停线程对象);
LockSupport.park();
//恢复某个线程的运行
/LockSupport.unpark(暂停线程对象);
如果打断标记已经是 true, 则 park 会失效
主线程与守护线程
默认情况下,
Java
进程需要等待所有线程都运行结束,才会结束。有一种特殊的线程叫做守护线程,只要其它非守护线程运行结束了,即使守护线程的代码没有执行完,也会强制结束。
线程的五种状态
这是从
操作系统
层面来描述的
![](https://img-blog.csdnimg.cn/f5dd8a2d7c4d4299a412db94eb0a008a.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA6Ju-5YS_6Zuq5p-z6buE6YeR57yV,size_20,color_FFFFFF,t_70,g_se,x_16)
【初始状态】仅是在语言层面创建了线程对象,还未与操作系统线程关联
【可运行状态】(就绪状态)指该线程已经被创建(与操作系统线程关联),可以由
CPU
调度执行
【运行状态】指获取了
CPU
时间片运行中的状态
当
CPU
时间片用完,会从【运行状态】转换至【可运行状态】,会导致线程的上下文切换
【阻塞状态】
如果调用了阻塞
API
,如
BIO
读写文件,这时该线程实际不会用到
CPU
,会导致线程上下文切换,进入 【阻塞状态】
等
BIO
操作完毕,会由操作系统唤醒阻塞的线程,转换至【可运行状态】
与【可运行状态】的区别是,对【阻塞状态】的线程来说只要它们一直不唤醒,调度器就一直不会考虑 调度它们
【终止状态】表示线程已经执行完毕,生命周期已经结束,不会再转换为其它状态
线程的六种状态
这是从
Java API
层面来描述的
根据
Thread.State
枚举,分为六种状态
![](https://img-blog.csdnimg.cn/ed7e740e4a804ef0a0eae60cb2fd576d.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA6Ju-5YS_6Zuq5p-z6buE6YeR57yV,size_20,color_FFFFFF,t_70,g_se,x_16)
NEW 线程刚被创建,但是还没有调用 start() 方法
RUNNABLE 当调用了 start() 方法之后,注意, Java API 层面的 RUNNABLE 状态涵盖了 操作系统 层面的 【可运行状态】、【运行状态】和【阻塞状态】(由于 BIO 导致的线程阻塞,在 Java 里无法区分,仍然认为 是可运行)
BLOCKED , WAITING , TIMED_WAITING 都是 Java API 层面对【阻塞状态】的细分(有机会再详细讲述)
TERMINATED 当线程代码运行结束