Java线程状态转换
来源:互联网 发布:淘宝如何抢秒杀商品 编辑:程序博客网 时间:2024/06/05 01:50
1.线程状态图
当我们new 一个Thread的时候,就是告诉CPU我们创建一个新的线程,这个时候只是创建过程。当我们开始为创建的线程调用start()的方法时,我们的线程就进入的就绪状态。所以我们一般不直接开始调用run的方法。就绪状态好了之后,就会反选run的方法。如果出现某种特殊的情况,那么线程可以还会进入就绪状态。例如,某个线程的优先级比较高的时候,需要它先使用。当然,在线程执行的时候,可能出现者线程进入休眠状、wait()的时候,使用线程挂起,那么线程处于阻塞状态。只有线程运行结束后,再也得不到CPU时间,它就结束了。如图所示。
2. 线程状态
我们继续上面的学习,这里我们可能说的线程状态词与上图不一样,我们用专业词来解说。
1) 新建(New):当线程被创建时,它会短暂地处于这种状态。此时它已经分配了必需的系统资源,并执行了初始化。此刻线程已经有资格获得CPU时间了,之后调度器将把这个线程转变为可运行状态或阻塞状态。
2) 就绪(Runnable):在这种状态下,只要调度器把时间片分配给线程,线程就可以运行。也就是说,在任意时刻可以运行也可以不运行。只需调度器能分配时间片给线程,它就可以运行;这不同于死亡和阻塞。
3) 阻塞(Blocked):线程能够运行,但有某个条件阻止它运行。线程处于阻塞状态时,调度器将忽略线程,不会分配给线程任何CPU时间。直到线程重新进入就绪状态,它才有可能执行操作。
4) 死亡(Dead):处于死亡或终止状态的线程将不再是可调度的。当线程再也不会得到CPU时间,它的任务已结束,或不再是可运行的。任务死亡的通常方式是从run()方法返回,但是任务的线程还可以被中断,你将要看到这一点。
3.进入阻塞状态
一个任务进入阻塞状态,可能的如下原因:
1) 通过调用sleep(milliseconds)使任务进入休眠状态,在这种情况下,任务在指定的时间内不会运行。
2) 你通过调用wait()使线程挡挂起。走到线程得到了notify()或notifyAll()消息,线程才会进入就绪状态。
3) 任务在等待某个输入、输出完成。
4) 任务试图在某个对象上调用其同步控制方法,但是对象锁不可用,因为另一个任务已经获取了这个锁。
4.线程控制基本方法
5. sleep方法使用
下面的例子,我们使用了Thread.sleep()的方法,说明当前的主线程(main)将会休眠多久时间,所以主线程 在休眠期间thread.interrupt()是不会被执行的,但是另外的新线程依然会在运行。当主线程醒来之后,就会执行interruput()的方法。这个方法是在Thread类的包中,方法将设置线程的中断状态。如果一个线程已经阻塞,或者试图执行一个阻塞操作,那么设置这个线程的中断状态将抛出InterruptedException.
package com.owen.thread;import java.util.Date;/** * 子线程在运行时,主线程休眠10秒 * * @author OwenWilliam 2016-7-21 * @since * @version v1.0.0 * */public class TestInterrupt{public static void main(String[] args){MyThread thread = new MyThread();thread.start();try{// 主线程休眠10秒Thread.sleep(10000);} catch (InterruptedException e){}// 断掉子线程,不要使用stop()方法,stop()会立刻停止,不会将flag设置为falsethread.interrupt();}}/** * 创建个线程,每隔一秒就打印出时间 * * @author OwenWilliam 2016-7-21 * @since * @version v1.0.0 * */class MyThread extends Thread{public void run(){boolean flag = true;while (flag){System.out.println("====" + new Date() + "====");try{// 休眠1秒sleep(1000);} catch (InterruptedException e){flag = false;return;}}}}
6. join方法使用
一个线程可以在其它线程之上调用join()方法,其效果是等待一段时间直到第二个线程结束才继续执行。如果某个线程在另一个线程t上调用t.join(),此线程被挂起,直到目标线程t结束才恢复(t.isAlive()返回为假)。届可以在调用join()时带上一个超时参数(单位可以是毫秒和纳秒),这样如果目标线程在这段时间到期还没有结束的话,join()方法总能返回。
下面的例子就是实现将t1的线程合并到主线程上,原先是有两条线程,现在join()之后变成了只有一条主线程子。所以要等t1.start()的方法执行好了之后才可以执行后面的线程。
package com.owen.thread;/** * 使用join()的方法,将MyThread2的线程合并到主线程中, 这个时候就相当于调用方法了, * 等待一个线程运行好了才可以运行下一个线程 * * @author OwenWilliam 2016-7-21 * @since * @version v1.0.0 * */public class TestJoin{public static void main(String[] args){MyThread2 t1 = new MyThread2("t1");t1.start();try{// 合并线程到主线程t1.join();} catch (InterruptedException e){}System.out.println("thread isAlive:" + t1.isAlive());for (int i = 1; i <= 10; i++){System.out.println("i am main thread");}}}/** * 创建线程,每隔1秒打印一行信息 * * @author OwenWilliam 2016-7-21 * @since * @version v1.0.0 * */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;}}}}
7.yield方法
在下面的例子中,我们使用了静态方法Thread.yield()调用是对线程调度器(Java线程机制的一部分,可以将CPU从一个线程转移到另一个线程)的一种建议,它声明:”我已经执行完生命周期中最重要的部分了,此刻正是切换给其他任务执行一段时间的大好时机。”
package com.owen.thread;/** * 测试Thread线程的yield的方法 * * @author OwenWilliam 2016-7-21 * @since * @version v1.0.0 * */public class TestYield{public static void main(String[] args){MyThread3 t1 = new MyThread3("t1");MyThread3 t2 = new MyThread3("t2");t1.start();t2.start();}}/** * 创建线程,当i的值为10的倍数时,那么就让出线程,给其它线程执行一会儿,注意是一会儿 * * @author OwenWilliam 2016-7-21 * @since * @version v1.0.0 * */class MyThread3 extends Thread{MyThread3(String s){super(s);}public void run(){for (int i = 1; i <= 100; i++){System.out.println(getName() + ": " + i);if (i % 10 == 0){// 让出线程一会儿yield();}}}}
8.线程的优先级别
线程持优先级将线程的重要性传递给了调度器。尽管CPU处理现有线程集的顺序是不确定的,但是调度器将倾向于让优先权最高的线程先执行。然而,这并不意味着优先权较低的线程将得不到执行(也就是说,优先权不会导致死锁)。优先级较低的线程仅仅是执行频率较低。
1) Java提供一个线程调度器来监控程序中启动后进入就绪状态的所有线程。线程调度器按照线程的优先级决定应调度哪个线程来执行。
2) 线程的优先级用数字表示,范围从1到10,一个线程的缺省优先级是5.
a) Thread.MIN_PRIORITY = 1
b) Thread.MAX_PRIOROTY = 10
c) Thread.NORM_PRIORITY = 5
3) 使用下述方法获得或设置线程对象的优先级。
a) int getPriority();
b) void setPriority(intnewPriority);
下面有例子中,我们分别在主线程上分出两条新的线程,它们分别 是t1和t2,所以正常情况下它们执行时间是相同的,也就是CPU会执行t1一会儿然后再执行t2一会儿,只是时间很快你感受不到,所以感觉就是多线程在执行。当我们在t1上加了优先级高之后,那么t1执行的时间就相对于t2要长一点了。
package com.owen.thread;/** * 测试线程的优先级使用 * @author OwenWilliam 2016-7-21 * @since * @version v1.0.0 * */public class TestPriority{public static void main(String[] args){Thread t1 = new Thread(new T1());Thread t2 = new Thread(new T2());//t1线程的优先级加3t1.setPriority(Thread.NORM_PRIORITY + 3);t1.start();t2.start();}}/** * 线程T1输出数据 * @author OwenWilliam 2016-7-21 * @since * @version v1.0.0 * */class T1 implements Runnable{@Overridepublic void run(){for (int i = 0; i < 1000; i++){System.out.println("T1:" + i);}}}/** * 线程T2的输出数据 * @author OwenWilliam 2016-7-21 * @since * @version v1.0.0 * */class T2 implements Runnable{@Overridepublic void run(){for (int i = 0; i < 1000; i++){System.out.println("T2----" + i);}}}
- Java线程状态转换
- java 线程状态转换
- Java线程状态转换
- Java线程状态转换
- Java线程状态转换
- Java线程状态转换
- Java线程状态转换
- Java线程的状态转换
- JAVA:线程状态的转换
- JAVA:线程状态的转换
- Java线程的状态转换
- Java线程状态转换图
- java 线程的状态转换
- 一、Java线程状态转换
- Java线程状态的转换
- java 线程的状态转换
- Java线程状态、状态转换的条件
- Java线程:线程状态的转换
- iOS 开发之KVO的底层实现
- Ubuntu 14.04的sources.list阿里的镜像。
- 多线段几何图形—— 简单几何图形(获取一个在图形内部的点)
- Android面试题目大全<完结部分>,Android笔试题目集锦
- Linux下多线程教程
- Java线程状态转换
- Struts1、struts2、springmvc比较
- 字符,字符串,字符指针,
- struts的html标签库
- Android ListView实现不同item的方法和原理分析
- 【生活】年化收益率、七日年化收益率这些事
- 几个简单的jQuery使用方法
- IDEA 旗舰版 使用Maven创建Web工程 并部署tomcat
- Android系统启动过程