1、线程的状态
(1)线程的生命周期可以分为4个阶段,即线程的4种状态,分为初始状态、可运行状态、阻塞状态和死亡状态;
(2)一个具有生命的线程,总是处于上述4种状态之一;
1)初始状态(New Thread):创建线程对象之后,尚未调用其start()方法之前,这个线程就有了生命,此时线程仅仅是一个空对象,系统没有为其分配资源。此时只能启动和终止线程,任何其它操作都会引发异常;
2)可运行状态(Runnable):当调用了start()方法启动线程之后,系统为该线程分配除CPU外的所需资源,这个线程就有了运行的机会,线程处于可运行的状态,在这个状态当中,该线程对象可能正在运行,也可能尚未运行;对于只有一个CPU的机器而言,任何时刻只能有一个处于可运行状态的线程占用处理机,获得CPU资源,此时系统真正运行线程的run()方法。
3)阻塞状态(Blocked):一个正在运行的线程因某种原因不能继续运行时,进入阻塞状态;阻塞状态是一种“不可运行”的状态,而处于这种状态的线程在得到一个特定的事件之后会转回可运行状态;
导致一个线程被阻塞有以下原因:
1)调用了Thread类的静态方法sleep();
2)一个线程执行到一个I/O操作时,如果I/O操作尚未完成,则线程将被阻塞;
3)如果一个线程的执行需要用一个对象的锁,而这个对象的锁正被别的线程占用,那么此线程被阻塞。
4)线程的suspend()方法被调用而使线程被挂起时,线程进入阻塞状态。但suspend()容易导致死锁,已经被JDK列为过期方法,基本不再使用。
5)处于阻塞状态的线程可以转回到可运行状态,例如,在调用sleep()方法之后,这个线程的睡眠时间已经达到了指定的间隔,那么它就有可能重新回到可运行状态。或当一个线程等待的锁变得可用的时候,那么这个线程也会从被阻塞的状态转入可运行状态。
4)死亡状态(Dead)
一个线程的run()方法运行完毕、stop()方法被调用或者在运行过程中出现未捕获的异常时,线程进入死亡状态。
2、线程调度
(1)当同一时刻有多个线程处于可运行状态,它们需要排队等待CPU资源,每个线程会自动获得一个线程的优先级(Priority),优先级的高低反映线程的重要或紧急程度。
(2)可运行的线程按优先级排队,线程调度依据建立在优先级基础上的“先到先服务”原则。
(3)线程调度管理器负责线程排队和在线程间分配CPU,并按线程调度算法进行调度。当线程调度管理器选中某个线程时,该线程获得CPU资源进入运行状态。
(4)线程调度是抢占式调度,即在当前线程执行过程中如果有一个更高优先级的线程进入可运行状态,则这个更高优先级的线程立即被调度执行。
1)线程优先级
线程的优先级用1~10表示,10表示优先级最高,默认值是5;每个优先级对应一个Thread类的公用静态常量public static final int NORM_PRIORITY=5;public static final int MIN_PRIORITY=1;public static final int MAX_PRIORITY=10;每个线程的优先级都介于Thread.MIN_PRIORITY和Thread.MAX_PRIORITY之间;线程的优先级可以通过setPriority(int grade)方法更改,此方法的参数表示要设置的优先级,它必须是一个1-10之间的整数。
2)实现线程调度的方法
join():join()方法 使当前线程暂停执行,等待调用该方法的线程结束后再继续执行本线程。它有3种重载形式:public final void join();public final void join(long mills);public final void join(long mills,int nanos);
sleep():sleep()方法会让当前线程睡眠(停止执行)millis毫秒,线程由运行中的状态进入不可运行状态,睡眠时间过后线程会再次进入可运行状态。语法结构如下:public static void sleep(long millis);
yield(): yield()方法可让当前线程暂停执行,允许其它线程执行,但该线程仍处于可运行状态,并不变为阻塞状态。此时,系统选择其他相同或更高优先级线程执行,若无其它相同或更高优先级线程,则该线程继续执行。
sleep()方法和yield()方法的区别:
sleep()方法:使当前线程进入被阻塞的状态;即使没有其他等待运行的线程,当前线程也会等待指定的时间;其他等待执行的线程的机会是均等的;
yelid()方法:将当前线程转入暂停执行的状态;如果没有其他等待执行的线程,当前线程会马上恢复执行;会运行优先级更高的线程。
关于线程调度的相关代码如下:
public class Wait {
/*
这是一个工具类,类中定义一个方法实现线程休眠指定秒数
*/
public static void waitBySecond(long Second){
for (int i = 1; i <= Second; i++) {
try {
//每循环1次,现成休眠1000毫秒(1秒)
System.out.println("休眠第"+i+"秒.......");
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}
public class Test {
public static void main(String[] args) {
System.out.println("main()方法开始执行");
//进行线程休眠
Wait.waitBySecond(10);
System.out.println("main()方法结束执行");
}
}
public class MyThread implements Runnable {
@Override
public void run() {
for (int i = 1; i <=20 ; i++) {
System.out.println(Thread.currentThread().getName()+"运行第"+ i+"次");
}
}
}
public class Test {
public static void main(String[] args) {
//创建MyTHread类对象
MyThread myThread = new MyThread();
Thread thread = new Thread(myThread,"java2320");
thread.start();
for (int i = 0; i <=30; i++) {
if (i == 10) {
try{
//让thread线程强制执行,一直执行完毕,才会执行其它线程
thread.join();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
System.out.println(Thread.currentThread().getName()+"正在运行"+i+"......");
}
}
}
public class MyThread implements Runnable {
@Override
public void run() {
for (int i = 1; i <=5 ; i++) {
System.out.println(Thread.currentThread().getName()+"正在运行:"+i);
if (i == 3) {
System.out.println("线程礼让:");
//线程礼让,将CPU资源释放出去后,线程还会去与其他线程一起抢占CPU资源,如果礼让出去之后又抢到资源,说明礼让没成功,如果礼让出去CPU资源,礼让成功
Thread.yield();
}
}
}
}
public class Test {
public static void main(String[] args) {
//创建MyThread类对象
MyThread myThread = new MyThread();
//
Thread thread1 = new Thread(myThread,"线程A");
Thread thread2 = new Thread(myThread,"线程B");
//设置线程的优先级
thread1.setPriority(1);
thread2.setPriority(10);
//开始线程
thread1.start();
thread2.start();
}
}