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()的详解分析
很经典的例子(生产者与消费者):
首先是消费者线程类:
接下来是生产者线程类:
最后是测试类:
运行结果如下所示:
线程是一个动态执行的过程,它也有一个从产生到死亡的过程。
(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个......
相关文章推荐
- Eclipse常用的快捷键大全
- JDK动态代理实现原理
- Eclipse启动报错
- java设计模式
- Java关键字(三)static关键字(static声明方法)
- eclipse run andriod程序提示Please ensure that adb is correctly located at 问题
- Windows8.1配置Java环境变量
- 8皇后以及N皇后算法探究,回溯算法的JAVA实现,非递归,循环控制及其优化
- (java多线程并发)concurrent包的实现
- Java的toString()方法
- spring bean的配置(一)
- (java并发)CAS操作原理以及Atomic的原理
- Java部分总结图片版2(已加上原图链接!!!)
- 慕课网 全面解析java注解
- java获取指定年月的开始时间与结束时间
- Java代码显示昨天当前时刻
- 仲恺ACM 1075:笨鸟先飞【java】
- MyEclipse中JavaMail冲突问题
- Spring简化配置
- JVM学习01-JVM内存模型