Java多线程(二)线程的生命周期、优先级和控制

Java多线程(二)线程的生命周期、优先级和控制

  线程的生命周期:线程主要有以下状态

 

    (1)创建

      当实例化一个Thread对象并执行start()方法后,线程进入“可执行”状态,开始执行,虽然多线程给用户一种同时执行的感觉,但事实上在同一时间点上只有一个线程在执行,只是线程之间转换的动作很快,所以看起来好像同时在执行一样。

    (2)可执行

      当线程启用start()方法后,进入“可执行”状态,执行用户覆写的run()方法。一个线程进入可执行状态,并不代表它可以一直执行到run()结束为止,事实上它只是加入此应用程序执行安排的队列中。这个线程加入了进程的线程执行队列中,对于大多数计算机来说,只有一个处理器,无法使多个线程同时执行,这时需要合理安排线程执行计划,让那些处于“可执行”状态下的线程合理共享cpu资源。所以,一个处于“可执行”状态下的线程,实际上可能正在等待取得cpu实践,也就是等候执行权,在何时给予线程执行权,则有java虚拟机和现成的优先级来决定。

    (3)非可执行

      在“可执行”状态下,线程可能被执行完毕,也可能没有执行完毕,处于等待执行权的队列中,线程离开”可执行“状态下的等待队列时,线程进入”非可执行“状态。可以使用Thread类中的wait()、sleep()方法使线程进入“非可执行“状态。当线程进入”非可执行“状态下,cpu不分配时间片给这个线程,若希望线程回到”可执行“状态时,可以使用notify()方法或者是notifyAll()方法以及interrupt()方法。

    (4)消亡

      当run()方法执行完毕后,线程自动消亡,当Thread类调用start()方法时,java虚拟机自动调用它的run()方法,而当run()方法结束时,该Thread会自动终止。以前Thread类中存在一个停止线程的stop()方法,不过现在已经被废弃了,因为调用这个方法,很容易使程序进入不稳定状态。

  线程的优先级:

  在Java语言中,线程有执行的优先,优先级的范围是1~10,默认值为5,可以使用Thread类中的setPriority()方法来设置线程的优先级,但必须是1~10的范围内,否则会出现异常。优先级较高的线程会被提前执行,当它执行完毕才会轮到优先权较低的线程执行如果优先级相同,那么采用轮流执行的方式。

  绝大多数操作系统都支持Time slicing, 简单地说就是操作系统会为每个线程分配一 小段CPU时间,时间一到就换下一个线程, 即便这个线程没有执行完毕。对于不支持 Time slicing的操作系统,每个线程必须执行完毕后,才轮到下一个线程,如果需要此线程礼让一下其他线程,可以使用Thread类中 的yield〇方法。

  线程的控制:

  线程的控制包括线程的启动、挂起、状态检查以及如何正确结束线程,由于在程序中使用多线程,为合理安排线程的执行顺序,可以对线程进行相应的控制。

 

  1.线程的启动

    一个新的线程被创建后处于初始状态,实际上并没有立刻进入运行状态,而是处理就绪状态,当轮到这个线程执行时,即进入“可执行”状态,开始执行线程run()方法中的代码。执行run()方法是通过调用Thread类中start()方法来实现的。调用start()方法启动线程的run()方法不同于一般的调用方法,一般方法必须等到方法执行完毕才能够返回。而对于start()方法来说,调用线程的start()方法后,startG方法告诉系统该线程准备就绪并可以启动run()方法后,就返回,并继续执行调用start()方法下面的语句,这时run()方法可能还在运行,这样,就实现了多任务操作。

 

  2.线程的挂起  

    当一个线程进入“非可执行”状态,也就是挂起状态时,必然存在某种原因使其不能继续运行,这些原因可能是如下几种情况。
    (1)通过调用sleep()方法使线程进入休眠状态,线程在指定时间内不会运行。
    (2)通过调用join()方法使线程挂起,如果线程A调用线程B的join()方法,那么线程A将被挂起,直到线程B执行完毕为止。
    (3)通过调用wait()方法使线程挂起,直到线程得到了notify()和notifyAll()消息,线程才会进入“可执行”状态。
    (4)线程在等待某个输入/输出完成。

  3.线程状态检查 

    一般情况下无法确定一个线程的运行状态,对于这些处于未知状态的线程,可以通过isAlive()方法来确定一个线程是否仍处在活动状态。当然即使处于活动状态的线程也并不意味着这个线程一定正在运行,对于一个已开始运行但还没有完成任务的线程,这个方法返回值为true。isAlive()方法用于测试线程是否处于活动状态。如果线程已经启动且尚未终止,则为活动状态。

 

   4.结束线程

    结束线程有两种情况:

    (1)自然消亡:一个线程从run()方法的结尾处返回,自然消亡且不能再被运行;
    (2)强制死亡:调用Thread类中stop()方法强制停止,不过该方法已经被废弃。
    虽然这两种情况都可以停止一个线程,但最好的方式是自然消亡,简单地说,如果要停止一个线程的执行,最好提供一个方式让线程可以完成run()的流程。

  5.后台线程

    后台线程,即Daemon(英文意思:守护神; (希腊神话中) 半人半神的精灵; [计] 守护进程;)线程,它是一个在后台执行服务的线程。例如操作系统中的隐藏线程和Java语言中的垃圾自动回收线程等。如果所有的非后台线程都结束了,则后台线程也会自动终止。可以使用Thread类中的setDaemon()方法来设置一个线程为后台线程。但是有一点值得注意:必须在线程启动之前调用setDaemon()方法,这样才能将这个线程设置为后台线程。当设置完成一个后台线程后,可以使用Thread类中的isDaemon()方法来判断线程是否是后台线程。

 

 

 

本文内容多参考书本知识,随笔记下来学习分享且方便以后查看。

posted @ 2018-01-13 02:35  maxudong  阅读(136)  评论(0编辑  收藏  举报