线程的五种状态及改变状态的三种方法

  1、新状态:线程对象已经创建,还没有在其上调用start()方法。

  2、可运行状态:当线程有资格运行,但调度程序还没有把它选定为运行线程时线程所处的状态。当start()方法调用时,线程首先进入可运行状态。在线程运行之后或者从阻塞、等待或睡眠状态回来后,也返回到可运行状态。

  3、运行状态:线程调度程序从可运行池中选择一个线程作为当前线程时线程所处的状态。这也是线程进入运行状态的唯一一种方式。

  4、等待/阻塞/睡眠状态:这是线程有资格运行时它所处的状态。实际上这个三状态组合为一种,其共同点是:线程仍旧是活的,但是当前没有条件运行。换句话说,它是可运行的,但是如果某件事件出现,他可能返回到可运行状态。

  5、死亡态:当线程的run()方法完成时就认为它死去。这个线程对象也许是活的,但是,它已经不是一个单独执行的线程。线程一旦死亡,就不能复生。如果在一个死去的线程上调用start()方法,会抛出java.lang.IllegalThreadStateException异常。

  1、睡眠

  Thread.sleep(long millis)和Thread.sleep(long millis, int nanos)静态方法强制当前正在执行的线程休眠(暂停执行),以“减慢线程”。当线程睡眠时,它入睡在某个地方,在苏醒之前不会返回到可运行状态。当睡眠时间到期,则返回到可运行状态。

  线程睡眠的原因:线程执行太快,或者需要强制进入下一轮,因为Java规范不保证合理的轮换。

package thread;

public class MulityT implements Runnable {
    private String s;
    private long i = 1;

    public MulityT(String s) {
        this.s = s;
    }

    @Override
    public void run() {
        // TODO Auto-generated method stub
        while (i < 10) {
            System.out.println(s + "=====" + i++);
//            Thread.yield();
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) throws InterruptedException {
        MulityT m = new MulityT("a");
        Thread t = new Thread(m);
        t.start();
        MulityT m2 = new MulityT("b");
        Thread t2 = new Thread(m2);
        t2.start();
        MulityT m3 = new MulityT("c");
        Thread t3 = new Thread(m3);
        t3.start();

    }

}

  输出结果:(每轮输出后暂停一秒左右)

a=====1
b=====1
c=====1
b=====2
a=====2
c=====2
c=====3
a=====3
b=====3
a=====4
c=====4
b=====4
a=====5
c=====5
b=====5
a=====6
c=====6
b=====6
b=====7
a=====7
c=====7
b=====8
a=====8
c=====8
c=====9
a=====9
b=====9

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

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

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

  2、线程的优先级和线程让步yield()

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

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

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

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

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

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

package thread;

public class MulityT implements Runnable {
    private String s;
    private long i = 1;

    public MulityT(String s) {
        this.s = s;
    }

    @Override
    public void run() {
        // TODO Auto-generated method stub
        while (i < 10) {
            System.out.println(s + "=====" + i++);
            Thread.yield();
        }
    }

    public static void main(String[] args) throws InterruptedException {
        MulityT m = new MulityT("a");
        Thread t = new Thread(m);
        t.start();
        MulityT m2 = new MulityT("b");
        Thread t2 = new Thread(m2);
        t2.start();
        MulityT m3 = new MulityT("c");
        Thread t3 = new Thread(m3);
        t3.start();

    }

}

  输出结果:

a=====1
c=====1
b=====1
c=====2
a=====2
b=====2
c=====3
a=====3
b=====3
c=====4
a=====4
b=====4
c=====5
a=====5
b=====5
c=====6
a=====6
b=====6
c=====7
b=====7
a=====7
c=====8
b=====8
c=====9
a=====8
b=====9
a=====9

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

  3、join()方法

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

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

package thread;

public class MulityT implements Runnable {
    private String s;
    private long i = 1;

    public MulityT(String s) {
        this.s = s;
    }

    @Override
    public void run() {
        // TODO Auto-generated method stub
        while (i < 10) {
            System.out.println(s + "=====" + i++);
        }
    }

    public static void main(String[] args) throws InterruptedException {
        MulityT m = new MulityT("a");
        Thread t = new Thread(m);
        t.start();
        MulityT m2 = new MulityT("b");
        Thread t2 = new Thread(m2);
        t2.start();
        t2.join();
        MulityT m3 = new MulityT("c");
        Thread t3 = new Thread(m3);
        t3.start();

    }

}

  输出结果:

a=====1
b=====1
a=====2
b=====2
a=====3
b=====3
a=====4
a=====5
b=====4
a=====6
b=====5
a=====7
b=====6
a=====8
b=====7
a=====9
b=====8
b=====9
c=====1
c=====2
c=====3
c=====4
c=====5
c=====6
c=====7
c=====8
c=====9

  小结:

  到目前位置,介绍了线程离开运行状态的3种方法:

  1、调用Thread.sleep():使当前线程睡眠至少多少毫秒(尽管它可能在指定的时间之前被中断)。

  2、调用Thread.yield():不能保障太多事情,尽管通常它会让当前运行线程回到可运行性状态,使得有相同优先级的线程有机会执行。

  3、调用join()方法:保证当前线程停止执行,直到该线程所加入的线程完成为止。然而,如果它加入的线程没有存活,则当前线程不需要停止。

时间: 2024-10-07 21:36:37

线程的五种状态及改变状态的三种方法的相关文章

线程的状态以及创建多线程的三种方式

首先了解一下线程的五种状态: 新建状态: 新建状态是指new之后,即新创建了一个线程的时候,此时并未运行任何线程方法体内的程序代码. 就绪状态: 简单来说就是指程序调用了start()之后,线程就得到了启动,代表线程进入了就绪状态,但是此时并不代表它会立刻去执行run()方法体内的程序代码,而是随时等待cpu的调度. 运行状态: 获得cpu的时间后,调用run()方法,进入运行状态. 阻塞状态: 由于某种原因放弃了cpu的会用权力,暂时停止运行,等待再次被调用. 死亡状态: 线程正常执行完毕,或

js中可以改变作用域的三种方式(改变this)

第一种方式:使用apply()方法: function sum(x, y) { alert(this); return x + y;//这里的this指的是callS对象方法 } function callS() { callS.callSum1(1, 2); } callS.callSum1 = function (x, y) { alert(this);//这里的this是callS方法 var s = sum.apply(this, arguments); return s; } call

LVS:三种负载均衡方式比较+另三种负载均衡方式

转:http://blog.csdn.net/u013256816/article/details/50705578 什么是LVS? ??首先简单介绍一下LVS (Linux Virtual Server)到底是什么东西,其实它是一种集群(Cluster)技术,采用IP负载均衡技术和基于内容请求分发技术.调度器具有很好的吞吐率,将请求均衡地转移到不同的服务器上执行,且调度器自动屏蔽掉服务器的故障,从而将一组服务器构成一个高性能的.高可用的虚拟服务器.整个服务器集群的结构对客户是透明的,而且无需修

第五周作业(Java多线程创建的三个方法)

我最近在学习Java中多线程,并且觉得多线程这块在以后的Java开发中显得极为重要,就谈一下Java实现多线程的三种方式. JAVA多线程实现方式主要有三种:继承Thread类.实现Runnable接口.使用ExecutorService.Callable.Future实现有返回结果的多线程.其中前两种方式线程执行完后都没有返回值,只有第三种是带返回值的,这种方式一般要求比较高,并且较前两种难一些. 1.继承Thread类实现多线程继承Thread类的本质上也是实现了Runnable接口的一个实

Linux中文本编辑器三种工作模式切换及vi编辑器三种工作模式下命令详解

文本编辑器的作用 创建或修改文本文件维护Linux系统中的各种配置文件Linux中最常用的文本编辑器Linux中最常用的文本编辑器vi:类UNIX操作系统的默认文本编辑器vim:vim时vi文本编辑器(一般简称vi编辑器)的增强版本 vi编辑器的工作模式 三种工作模式命令模式.输入模式.末行模式不同模式之间的切换 命令模式的基本操作3-1 光标移动方向键移动(↑.↓.←.→) 功能:上下左右移动Page Down或Ctrl+F 功能:向下翻动一整页的内容Page Up或Ctrl+B 功能:向上翻

C#在Winform中改变Textbox高度三种方法

最近在做C# Winform项目,需要有一个能动态调整大小的Textbox,并且要是单行的.试了几次,单行模式的Textbox不能直接改高度.于是搜索了一下,整理出几个改变高度的方法. 1.将Textbox改为多行模式,设置MutliLine属性为True,然后屏蔽Enter键. private void txtTest_KeyDown (object sender, KeyEventArgs e){if ((int)e.KeyCode == 13){e.SuppressKeyPress = t

JQuery的几种页面加载完执行三种方式

jquery加载页面的方法(页面加载完成就执行) 1. 1 $(function(){ 2 $("#a").click(function(){ 3 //adding your code here 4 }); 5 }); 2. 1 $(document).ready(function(){ 2 $("#a").click(function(){ 3 //adding your code here 4 }); 5 }); 3. 1 window.onload = fun

【计算机网络】关于三种网络通信模式以及java中三种通信方式的实现介绍

当前的网络中有三种通讯模式:单播.广播.组播(多播),其中的组播出现时间最晚但同时具备单播和广播的优点,最具有发展前景. 一.单播: 主机之间"一对一"的通讯模式,网络中的交换机和路由器对数据只进行转发不进行复制.如果10个客户机需要相同的数据,则服务器需要逐一传送,重复10次相同的工作.但由于其能够针对每个客户的及时响应,所以现在的网页浏览全部都是采用IP单播协议.网络中的路由器和交换机根据其目标地址选择传输路径,将IP单播数据传送到其指定的目的地. 单播的优点: 1.  服务器及时

Hibernate 入门 04 - Hibernate中Java对象的三种状态

目录:(后续不断更新...) Hibernate 入门 01 - 框架技术 (介绍Hibernate框架的发展由来) Hibernate 入门 02 - Hibernate介绍及其环境搭建 Hibernate 入门 03 - 使用Hibernate完成持久化操作 Hibernate 入门 04 - Hibernate中Java对象的三种状态 ▁▃▅ Hibernate中Java对象的三种状态▅▃▁ 1. Java对象的三种状态 当应用通过调用Hibernate API与框架发生交互时,需要从持久