新建和就绪状态
当程序使用new关键字创建了一个线程后,该线程就处于新建状态. JVM为Thread对象分配内存.初始化其成员变量的值.
线程对象调用start()方法之后,该线程处于就绪状态. JVM会为其创建方法调用栈和程序计数器.
就绪状态的线程并没有开始运行,它只是表示该线程可以运行了. JVM的线程调度器调度该线程运行.
注意:
1.调用start()启动线程之后,run()方法才会被看作线程执行体.
2.直接调用run()方法,则run()方法就只是一个普通方法.
运行和阻塞状态
就绪状态的线程获得了CPU,开始执行run方法的线程执行体.则该线程处于运行状态.
线程在执行过程中可能会被中断,以使其他线程获得执行的机会,线程调度取决于底层平台采用的策略.
现代桌面和服务器操作系统一般都采用抢占式策略。一些小型设备如手机则可能采用协作式调度.
抢占式策略的系统:系统给每个可执行的线程一个小时间段来处理任务;当该时间段用完,系统会剥夺该线程所占有的资源,让其他线程获得执行机会.在选择下一个线程时,系统会考虑线程的优先级.
线程进入阻塞状态:
1.线程调用sleep方法主动放弃所占用的处理器资源.
2.线程调用了一个阻塞式的IO方法,该方法返回之前,该线程被阻塞.
3.线程试图获得一个同步监视器,但同步监视器正被其他线程所持有.
4.线程在等待某个通知(notify).
5.线程调用了线程的suspend方法将线程挂起.不过这个方法容易导致死锁,所以程序应该尽量避免使用该方法.
阻塞线程重写进入就绪状态:
1.调用sleep方法的线程经过了指定的时间.
2.线程调用的阻塞式IO方法已经返回.
3.线程成功地获得了试图取得同步监视器.
4.线程正在等待某个通知时,其他线程发出了一个通知.
5.处于关闭状态的线程被调用了resume恢复方法.
线程死亡
线程在以下情况下死亡:
run()方法执行完成,线程正常结束.
线程抛出一个未捕获的Exception或Error.
直接调用该线程的stop()方法来结束该线程.该方法容易导致死锁,通常不推荐使用.
Thread对象的isAlive()方法,查看线程是否死亡。
注意:
死亡的线程不能再用start()方法重新启动。
一个线程的start()方法不能两次调用。
线程睡眠:sleep
sleep方法,将线程转入阻塞状态.时间到即再转入就绪状态.
线程让步:yeild
yeild()方法,将线程转入就绪状态。该方法让线程暂停一下,让系统重新调度一次。
sleep方法和yeild方法的区别:
sleep方法暂停期间不会给其他线程执行机会.
sleep方法会将线程转入阻塞状态,知道经过阻塞时间才会转入就绪状态.yeild直接把线程转入就绪状态.
sleep方法抛出InterruptedException异常,所以调用sleep()时要捕捉或抛出异常.而yeild()方法则没有声明抛出任何异常.
sleep方法比yeild法那个发有更好的移植性,通常不要依靠yeild来控制并发线程的执行.
join线程
在某个线程的执行流中调用其他线程的join()方法时,调用线程将被阻塞,直到被join方法加入的join线程完成为止。
例:
public class TestJoin {
public static void main(String[] args) {
MyThread2 t1 = new MyThread2("abcde");
t1.start();
try {
t1.join();
} catch (InterruptedException e) {}
for(int i=1;i<=10;i++){
System.out.println("i am main thread");
}
}
}
class MyThread2 extends Thread {
MyThread2(String s){
super(s);
}
public void run(){
for(int i =1;i<=10;i++){
System.out.println("i am "+getName());
try {
sleep(1000);
} catch (InterruptedException e) {
return;
}
}
}
}
线程优先级
每个线程都有优先级.优先级高的线程获得较多的执行机会.
默认情况下,main线程具有普通优先级.
每个线程默认优先级与创建它的父线程具有同样的优先级.
Java提供的优先级范围是1~10.默认优先级为5.
Thread提供静态常量:
static int MAX_PRIORITY 线程可以具有的最高优先级。 值为10.
static int MIN_PRIORITY 线程可以具有的最低优先级。值为1.
static int NORM_PRIORITY 分配给线程的默认优先级。值为5.
注意:
不同操作系统的优先级不同.应尽量避免直接为线程指定优先级,而应使用以上三个静态常量类设置优先级.
后台线程
运行在后台,用于为其他线程提供服务.又称为”守护线程”.
如果所有前台线程死亡,后台线程也会死亡.
调用Thread对象的setDeamon(true)方法可以将指定线程设置成后台线程.
所有前台线程死亡时,后台线程随之死亡.
Thread对象的isDeamon()方法用于判断指定线程是否为后台线程.
说明:
main方法的主线程是前台线程.
前台线程创建的线程默认是前台线程.
后台线程创建的线程默认是后台线程.
停止线程
需要停止线程不要去调用stop()方法。而是为线程类设置一个运行标志符。
例:
public class TestThread4 {
public static void main(String args[]){
Runner4 r = new Runner4();
Thread t = new Thread(r);
t.start();
for(int i=0;i<100000;i++){
if(i%10000==0 & i>0)
System.out.println("in thread main i=" + i);
}
System.out.println("Thread main is over");
r.shutDown();
//t.stop();
}
}
class Runner4 implements Runnable {
private boolean flag=true;
public void run() {
int i = 0;
while (flag==true) {
System.out.print(" " + i++);
}
}
public void shutDown() {
flag = false;
}
}