一、系统调度
1、进程的调度
2、线程的调度
抢占式的系统调度:
为每个线程分配一个时间片,当时间片用完,操作系统剥夺该线程的运行权,并给另外一个线程一个机会来运行,此时考虑线程的优先级。所有的桌面和服务器的操作系统都使用抢占式调度。
协作式的系统调度:
一个线程只有在调用yeild方法或被阻塞或等待时才失去控制权,像手机等小型设备。
二、线程的状态
1、分类
在Java中线程的状态可以分为以下六种,该状态在java.lang.Thread.State有所描述:
NEW —(新建)
RUNNABLE —(可运行)
BLOCKED —(阻塞)
WAITING —(等待)
TIMED_WAITING —(计时等待)
TERMINATED —(终止)
2、阻塞与等待
2.1、等待概念
等待是主动的等待,当线程等待另一个线程通知调度器出现一个条件时,线程进入等待状态(此处的条件也课程称之为条件对象)。比如:调用Object.await()、Thread.join方法,或者等待java.util.concurrent库中的Lock或Condition时。
2.2、阻塞的概念
阻塞时被动的阻塞,等一个线程视图获取对象锁时(非java.util.concurrent库中的锁),但此时该锁被另外一个线程所持有,线程进入阻塞状态。
该状态下,线程无法执行同步代码块或方法的代码。
3、状态介绍
3.1 NEW ---- 新建
即当使用new 操作符创建一个新线程时,比如 new Thread( ) ,此时线程还没有开始运行。
3.2 RUNNABLE — 可运行
即一旦线程调用了start方法,该线程就处于可运行状态。(Java规范中没有将线程的正在运行作为一个单独状态。一个正在运行的线程仍然处于可运行状态)。
线程是否运行取决于调度器是否给他分配了时间片。
3.3 BLOCKED — 阻塞
被阻塞等待监视器锁的线程处于这种状态(即synchorized与之相关联的Clsss对象)。
状态转换:
可运行状态 —> 阻塞状态:
当一个线程试图获取一个内部的对象锁(并非java.util.concurrent中Lock),而这个锁正在由其他线程占有,该线程就会被阻塞。
阻塞状态 —> 可运行状态:
当其他线程释放了这把锁,而线程调度器又允许该线程拥有这把锁,此时线程变成可运行状态。
3.4 WAITING — 等待
无限期等待另一个线程执行特定操作的线程处于此状态
状态转换:
可运行状态 —> 等待状态
当调用以下方法会进入等待状态:
Object.wait
Thread.join
LockSupport.park
等待java.until.concurrent中的Lock或Condition的await时也会进入等待状态:
Locak.lock
Condition.await
等待状态 ---->可运行状态:
处于等待状态的线程正在等待另一个线程执行特定的操作,一旦执行该特定操作就处于可运行状态。
例如:
另外一个线程在该对象上调用notify()或notifyall()。
另外一个线程调用了与之相关的条件对象(即Condition对象)的signal()或signalAll()
调用了join()的线程正在等待指定的线程终止。
LockSupport.unpark
Locak.unlock
发生中断(wait、join为可中断方法)
2.5 TIMED_WAITING —(计时等待)
等待另一个线程执行操作并指定等待时间的线程处于此状态,与等待状态不同的是可以指定超时参数
状态转换:
可运行状态 ----> 计时等待状态:
调用以下方法会让线程处于计时等待状态:
Object.wait
Thread.join
LockSupport.parkNanos
LockSupport.parkUntil
Thread.sleep(…)
java.until.concurrent中Lock的tryLock尝试获取锁或Condition的await()时也会进入计时等待状态:
Lock.tryLock
Condition.await
计时等待状态 ----> 可运行状态:
当超时期满或收到恰当的通知就会处于活动状态(即可运行状态)(参考上面的等待状态)。
2.6 TERMINATED —(终止)
即 run方法执行结束 或 未捕获的异常终止了run方法,使线程意外终止。
参考:
Java核心技术卷