java多线程学习3-线程状态转换

线程的5个状态可分为,分别是新、死、可运行、运行、阻塞状态。可以用如下一幅图表示:

1、 初生状态:已创建线程对象,但没有执行start()方法的线程;

2、 可运行状态:已执行start()方法,并满足运行条件,等待CPU调度;

3、 运行状态:正在CPU上运行;

4、 死亡状态:线程运行结束,也就是run()方法运行结束;

5、 阻塞状态:正在运行的线程因为某些原因,如CPU调度策略,或者有更高优先级的进程要运行,或者运行的条件不满足等,暂停执行。

下面介绍通过睡眠和等待来控制线程。

1、 睡眠

可以在线程的run()方法中调用Thread.sleep(long millis)和Thread.sleep(long millis, int nanos)静态方法强制当前正在执行的线程休眠(暂停执行),

 

class Demo3 extends Thread{

@Override

public void run() {

for(int i = 5;i<11;i++){

System.out.println("这里线程睡眠5秒钟");

try {

Thread.sleep(2000);

} catch (InterruptedException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

System.out.println("线程运行结束");

}

}

这样执行的结果就是每隔两秒钟打印一句。

注意:

a、线程睡眠是帮助所有线程获得运行机会的最好方法。

b、线程睡眠到期自动苏醒,并返回到可运行状态,不是运行状态。sleep()中指定的时间是线程不会运行的最短时间。因此,sleep()方法不能保证该线程睡眠到期后就开始执行。

c、sleep()是静态方法,只能控制当前正在运行的线程。

 

2、线程让步yield()

要理解yield(),必须了解线程的优先级的概念。线程总是存在优先级,优先级范围在1~10之间。JVM线程调度程序是基于优先级的抢先调度机制。在大多数情况下,当前运行的线程优先级将大于或等于线程池中任何线程的优先级。但这仅仅是大多数情况。

 

注意:当设计多线程应用程序的时候,一定不要依赖于线程的优先级。因为线程调度优先级操作是没有保障的,只能把线程优先级作用作为一种提高程序效率的方法,但是要保证程序不依赖这种操作。

 

当线程池中线程都具有相同的优先级,调度程序的JVM实现自由选择它喜欢的线程。这时候调度程序的操作有两种可能:一是选择一个线程运行,直到它阻塞或者运行完成为止。二是时间分片,为池内的每个线程提供均等的运行机会。

 

设置线程的优先级:线程默认的优先级是创建它的执行线程的优先级。可以通过setPriority(int newPriority)更改线程的优先级。例如:

Thread t = new MyThread();
t.setPriority(8);
t.start();

线程优先级为1~10之间的正整数,JVM从不会改变一个线程的优先级。然而,1~10之间的值是没有保证的。一些JVM可能不能识别10个不同的值,而将这些优先级进行每两个或多个合并,变成少于10个的优先级,则两个或多个优先级的线程可能被映射为一个优先级。

 

线程默认优先级是5,Thread类中有三个常量,定义线程优先级范围:

static int MAX_PRIORITY
线程可以具有的最高优先级。
static int MIN_PRIORITY
线程可以具有的最低优先级。
static int NORM_PRIORITY
分配给线程的默认优先级。

 

Thread.yield()方法作用是:暂停当前正在执行的线程对象,并执行其他线程。

yield()应该做的是让当前运行线程回到可运行状态,以允许具有相同优先级的其他线程获得运行机会。因此,使用yield()的目的是让相同优先级的线程之间能适当的轮转执行。但是,实际中无法保证yield()达到让步目的,因为让步的线程还有可能被线程调度程序再次选中。

结论:yield()从未导致线程转到等待/睡眠/阻塞状态。在大多数情况下,yield()将导致线程从运行状态转到可运行状态,但有可能没有效果。

 

3、join()方法

 

Thread的非静态方法join()让一个线程B“加入”到另外一个线程A的尾部。在A执行完毕之前,B不能工作。例如:

Thread t = new MyThread();
t.start();
t.join();

另外,join()方法还有带超时限制的重载版本。 例如t.join(5000);则让线程等待5000毫秒,如果超过这个时间,则停止等待,变为可运行状态。

 

package learn.thread;

 

public class LearnThree {

 

public static void main(String[] args) {

Demo3 demo = new Demo3();

 

for (int i = 0; i < 1000; i++) {

System.out.println(Thread.currentThread().getName()+"这是中main线程中。");

if (5 == i) {

demo.start();

try {

 

demo.join();

} catch (InterruptedException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

 

}

}

}

 

class Demo3 extends Thread {

 

@Override

public void run() {

for (int i = 5; i < 11; i++) {

System.out.println("这里线程睡眠5秒钟");

// Thread.sleep(2000);

Thread.yield();

}

System.out.println("线程运行结束");

}

}

参考:http://lavasoft.blog.51cto.com/62575/99153

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值