您的位置:首页 > 编程语言 > Java开发

java线程的生命周期及wait(),notify(),notifyAll()的详解分析

2016-01-02 23:22 1046 查看
1.java线程的生命周期
    线程是一个动态执行的过程,它也有一个从产生到死亡的过程。
(1)生命周期的五种状态

    新建(new Thread)
    当创建Thread类的一个实例(对象)时,此线程进入新建状态(未被启动)。

    例如:Thread  t1=new Thread();

    就绪(runnable)
    线程已经被启动,正在等待被分配给CPU时间片,也就是说此时线程正在就绪队列中排队等候得到CPU资源。例如:t1.start();

    运行(running)
    线程获得CPU资源正在执行任务(run()方法),此时除非此线程自动放弃CPU资源或者有优先级更高的线程进入,线程将一直运行到结束。

    死亡(dead)
    当线程执行完毕或被其它线程杀死,线程就进入死亡状态,这时线程不可能再进入就绪状态等待执行。

    自然终止:正常运行run()方法后终止

    异常终止:调用方法stop()让一个线程终止运行

    堵塞(blocked)

    由于某种原因导致正在运行的线程让出CPU并暂停自己的执行,即进入堵塞状态。

    正在睡眠:用sleep(long t) 方法可使线程进入睡眠方式。一个睡眠着的线程在指定的时间过去可进入就绪状态。

    正在等待:调用wait()方法。(调用motify()方法回到就绪状态)

    被另一个线程所阻塞:调用suspend()方法。(调用resume()方法恢复)

2.常用方法

setPriority( ) 设置线程的优先权;



void run()   创建该类的子类时必须实现的方法

void start() 开启线程的方法

static void sleep(long t) 释放CPU的执行权,不释放锁

final void wait() 释放CPU的执行权,释放锁。类似sleep( ), 不同的是,wait( )会先释放锁住的对象,然后再执行等待的动作。注意,这个函数属于          
                       Object类。另外,由于wait( )所等待的对象必须先锁住,因此,它只能用在同步化程序段或者同步化方法内,否则,会抛出异                                         常IllegalMonitorStateException.

final void notify() 唤醒在此对象监视器上等待的单个线程。如果所有线程都在此对象上等待,则会选择唤醒其中一个线程(随机)。直到当前的线程                                     放弃此对象上的锁,才能继续执行被唤醒的线程。同Wait方法一样,notify只能由持有对像锁的线程来调用.notifyall也一样,不  
                                    同的是notifyall会唤配所有在此对象锁上等待的线程。"只能由持有对像锁的线程来调用"说明wait方法与notify方法必须在同步块

                            内执行,即synchronized(obj)之内.再者synchronized代码块内没有锁是寸步不行的,所以线程要继续执行必须获得锁,相辅相成.

join( ): 等待加入的线程执行完毕才会执行下一个线程。加入的线程通过interrupt( )来唤醒。

static void yied()暂停线程的执行,给其它具有相同优先权的线程执行的机会,若此时没有其它线程执行,则此线程继续执行。这个函数并不会释                      
            放锁住的对象。

      wait导致当前的线程等待,直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法,或被其他线程中断。wait只能由持有对像锁的线程来调用。

       注意:

wait(),notify(),notifyAll()不属于Thread类,而是属于Object基础类,也就是说每个对象都有wait(),notify(),notifyAll()的功能.因为每个对象都有锁,锁是每个对象的基础,当然操作锁的方法也是最基础了。

3.wait(),notify(),notifyAll()的详解分析

很经典的例子(生产者与消费者):

首先是消费者线程类:

import java.util.List;
public class Consume implements Runnable {
private List container = null;
private int count;
public Consume(List lst) {
this.container = lst;
}
public void run() {
while (true) {
synchronized (container) {
if (container.size() == 0) {
try {
container.wait();// 容器为空,放弃锁,等待生产
} catch (InterruptedException e) {
e.printStackTrace();
}
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
container.remove(0);
container.notify();
System.out.println("我吃了" + (++count) + "个");
}
}
}
}


接下来是生产者线程类:

import java.util.List;
public class Product implements Runnable {
private List container = null;
private int count;
public Product(List lst) {
this.container = lst;
}
public void run() {
while (true) {
synchronized (container) {
if (container.size() > MultiThread.MAX) {
// 如果容器超过了最大值,就不要在生产了,等待消费
try {
container.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
container.add(new Object());
container.notify();
System.out.println("我生产了" + (++count) + "个");
}
}
}
}


最后是测试类:

import java.util.ArrayList;
import java.util.List;
public class MultiThread {
private List container = new ArrayList();
public final static int MAX = 10;
public static void main(String args[]) {
MultiThread m = new MultiThread();
new Thread(new Consume(m.getContainer())).start();
new Thread(new Product(m.getContainer())).start();
}
public List getContainer() {
return container;
}
public void setContainer(List container) {
this.container = container;
}
}


运行结果如下所示:

我生产了1个
我吃了1个
我生产了2个
我生产了3个
我生产了4个
我生产了5个
我生产了6个
我生产了7个
我吃了2个
我生产了8个
我吃了3个
我生产了9个
我吃了4个
我吃了5个
我吃了6个
我吃了7个
我吃了8个
我生产了10个
我生产了11个
我吃了9个
我生产了12个
我吃了10个
......
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: