线程的调度
JVM的线程调度模型基本上是由操作系统决定的,调度模型分为两种:
- 分时调度模型: 系统平均分配CPU时间片,所有线程轮流占用CPU
- 抢占式调度模型: 系统根据线程优先级分配CPU时间片,优先级高的优先分配CPU时间片,如果优先级相同,则随机选择一个.
JAVA使用的是抢占式调度模型 - 线程都有优先级
- 可以设置线程的优先级从1到10,数值越高,优先级越高
- 优先级高的线程代表获取CPU时间片的概率高,并非一定优先执行
线程的状态
JAVA的Thread类声明了一下六中状态:
public enum State {
NEW,// 新建
RUNNABLE,// 可执行,包含操作系统的就绪,运行两种状态
BLOCKED,// 阻塞
WAITING,// 等待
TIMED_WAITING,// 限时等待
TERMINATED;// 终止
}
Thread对象的主要方法:
- start():启动线程
- run():线程在RUNNABLE状态下获取CPU时间片,执行代码
- sleep():使线程进入TIMED_WAITING状态
- stop():强制线程进入TERMINATED状态,危险操作,容易导致资源中断等问题
- interrupt():
(1)如果此线程处于阻塞状态(如调用了Object.wait()方法),就会立马退出阻塞,并抛出InterruptedException异常,线程就可以通过捕获InterruptedException来做一定的处理,然后让线程退出。更确切地说,如果线程被Object.wait()、Thread.join()和Thread.sleep()三种方法之一阻塞,此时调用该线程的interrupt()方法,该线程将抛出一个InterruptedException中断异常(该线程必须事先预备好处理此异常),从而提早终结被阻塞状态。
(2)如果此线程正处于运行之中,线程就不受任何影响,继续运行,仅仅是线程的中断标记被设置为true。所以,程序可以在适当的位置通过调用isInterrupted()方法来查看自己是否被中断,并执行退出操作。 - join():下面例子,当ThreadA实例调用start()后,ThreadA的实例,需要等待threadb执行完才会继续向下执行.
class ThreadA extends Thread
{
void run()
{
Thread threadb = new Thread("thread-b");
threadb.start();
threadb.join();
}
}
注意:
1. threadb.start()被调用时,才会执行阻塞ThreadA的实例.虽然直接调用join()方法并不会报错,但若threadb没有启动(start),自然也不会执行threadb的run()方法,这也就失去了意义.
2. join()方法允许传入时间参数(如:join(1000)),如果设置了时间ThreadA的实例会被设置为TIMED_WAITING状态,如果没有设置时间,则会被设置成WAITING状态.
- yield():让步,使正在执行的线程转入就绪状态,重新等待CPU分配时间片;注意yield()方法不会阻塞线程
- deamon操作:将线程设置为守护线程
- 只要JVM实例中尚存在任何一个用户线程没有结束,守护线程就能执行自己的工作;只有当最后一个用户线程结束,守护线程随着JVM一同结束工作。
- 守护线程和用户线程的区别:二者与JVM虚拟机进程终止的方向不同。用户线程和JVM进程是主动关系,如果用户线程全部终止,JVM虚拟机进程也随之终止;守护线程和JVM进程是被动关系,如果JVM进程终止,所有的守护线程也随之终止
- 守护线程创建的线程也是守护线程
- 守护线程可以在启动后,通过setDeamon()方法,设置成用户线程,但守护线程的声明,只能在启动之前,启动后的用户线程不能再通过setDeamon()方法设置成守护线程
其他
- BLOCKED状态:当因为获取不到锁而无法进入同步块时,线程处于BLOCKED状态.这种状态通常发生在同步代码块调用时,线程需要获取锁的时候.
- 进入BLOCKED状态、WAITING状态、TIMED_WAITING状态的线程都会让出CPU的使用权;另外,等待或者阻塞状态的线程被唤醒后,进入Ready状态,需要重新获取时间片才能接着运行。
本文由 momoker 创作,采用 知识共享署名4.0
国际许可协议进行许可
本站文章除注明转载/出处外,均为本站原创或翻译,转载前请务必署名
最后编辑时间为: Apr 13,2023