多线程的生命周期

实现多线程的两种方式:继承Thread类或是实现Runnable接口,推荐后者
线程所拥有的状态:初始状态,可运行状态,运行状态,阻塞状态,锁池状态,等待队列,终止状态。
线程的生命状态:
1.当线程类被创建后就进入初始化状态。
2.当调用.start()方法时就拿到对象锁,进入可运行状态(一旦获取cpu资源就会进入运行状态)
3.当处于可运行状态的线程拿到cpu分配的时间片就进入运行状态。
3.1.如果处于运行状态的线程的main方法或是run方法执行完,线程就进入终止状态。
3.2.如果当前处于运行状态的线程调用sleep()方法或是join()方法,线程就进入阻塞状态。此时不释放资源(主要指对象锁)。当睡眠时间结束后进入可运行状态,等待获取cpu的时间片。
3.3.当处于运行状态的当前线程调用yield方法,线程就会放弃当前时间片回到可运行状态。和其他线程再次竞争。
3.4.当进入运行状态的线程调用wait方法后就会进入等待状态。只有调用了notify(只唤醒一个线程不确定唤醒哪个线程)或是notifyAll方法会后进入锁池状态。拿到对象锁标记后会进入可运行状态。
3.5.当运行状态的线程发现要使用的资源被同步时,会进入锁池状态,当拿到对象锁后会进入可运行状态。

注:yield就是当当前线程临时暂停让其他线程运行。
   join方法表示run方法完成后台程序在继续执行。也就是合并子线程到主线程里,是程序顺序执行。
如:thread1.join();  // 等线程thread1结束后再继续执行  
使用interrupt方法终止线程

使用interrupt方法来终端线程可分为两种情况:
(1)线程处于阻塞状态,如使用了sleep方法。
(2)使用while(!isInterrupted()){...}来判断线程是否被中断。
在第一种情况下使用interrupt方法,sleep方法将抛出一个InterruptedException例外,而在第二种情况下线程将直接退出。
在Thread类中有两个方法可以判断线程是否通过interrupt方法被终止。一个是静态的方法interrupted(),一个是非静态的方法isInterrupted(),这两个方法的区别是interrupted用来判断当前线是否被中断,而isInterrupted可以用来判断其他线程是否被中断

线程声明周期总结:
当一个线程类被new出来以后就进入了初始化状态,当调用线程的start的方法以后就进入可运行状态,可运行状态表示该线程已经具备了运行条件就等待分配cpu的时间片就可以运行了。当获取到时间片以后就进入了运行状态。
情况一:进入运行状态后,执行完main方法等就进入终结状态。
情况二:进入运行状态后,调用Thread的sleep方法或是join方法,就进入阻塞状态当,当睡眠时间过了后就进入可运行状态,等待获取时间片接着运行。
情况三:进入运行状态以后,调用yield方法后会放弃时间片,进入可运行状态,再次获取时间片后才接这运行。
情况四:当进入运行状态后,当要调用的资源已经被其他线程占用,即不能拿到对象锁,就会进入锁池,先进先拿,等拿到对象锁后会进入可运行状态,活取到时间片后接着运行。
情况5:当进入运行状态后,当调用对象的wait方法后,会进入等待队列,当调用notify方法或是notifyAll方法后进入锁池。拿取到对象锁后,再进入可运行状态


线程one经过了500ms的sleep后,在某一时刻再次获得时间片,它将接着上一次的断点运行

死锁实例
1.public class DeadLockOneRunnable implements Runnable {  
2.    private byte [] bytes;  
3.    public DeadLockOneRunnable (byte [] bytes) {  
4.        this.bytes= bytes;  
5.    }  
6.    @Override 
7.    public void run() {  
8.        synchronized (bytes) {  
9.            while(true) {  
10.                System.out.println(Thread.currentThread().getName() + "is running...");  
11.            }  
12.        }  
13.    }  
14. 
15.    public static void main(String[] args) {  
16.        byte [] bytes = new byte[0];  
17.        DeadLockOneRunnable run = new DeadLockOneRunnable(bytes);  
18.        Thread thread = new Thread(run, "thread");  
19.        thread.start();  
20.        synchronized (bytes) {  
21.            try {  
22.                thread.join();  
23.            } catch (InterruptedException e) {  
24.                e.printStackTrace();  
25.            }  
26.        }  
27.        System.out.println("main thread run over .");  
28.    }  
29.} 
public class DeadLockOneRunnable implements Runnable {
private byte [] bytes;
public DeadLockOneRunnable (byte [] bytes) {
this.bytes= bytes;
}
@Override
public void run() {
synchronized (bytes) {
while(true) {
System.out.println(Thread.currentThread().getName() + "is running...");
}
}
}

public static void main(String[] args) {
byte [] bytes = new byte[0];
DeadLockOneRunnable run = new DeadLockOneRunnable(bytes);
Thread thread = new Thread(run, "thread");
thread.start();
synchronized (bytes) {
try {
thread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("main thread run over .");
}
}        说明:在main线程中获得了对象bytes的lock,然后线程thread通过join()方法,则主线程main必须要等到thread线程终止后才可以继续往下运行。但是,当线程thread运行后,发现在其run()方法内部synchronized(bytes),那么线程thread也需要持有对象bytes的lock才可以运行。此时的情况为main线程持有对象bytes的lock等待线程thread运行终止后运行,而线程thread又需要对象bytes的lock被释放;两个线程相互等待彼此的资源,产生死锁。

猜你喜欢

转载自jameszhao1987.iteye.com/blog/1273046