当JVM加载代码,发现main方法之后,就会启动一个线程,这个线程称为“主线程”(main线程),该线程负责执行main方法。那么在main方法执行中再创建的其他线程就称为程序中的其他线程。

如果main方法中又创建了其他线程,那么JVM就要在主线程和其他线程之间轮流切换,保证每个线程都有机会使用CPU资源,main方法即使执行完最后的语句(主线程结束),JVM也不会结束java应用程序,JVM一定要等到Java应用程序中的所有线程都结束之后,才结束java应用程序。

java语言使用Thread类及其子类的对象来表示线程,新建的线程在它的一个完整的生命周期中通常要经历如下的四种状态。

1.新建

当一个Thread类或其子类的对象被声明并创建时,新生的线程对象处于新建状态。此时它已经有了相应的内存空间和其他资源。

2.运行

线程创建之后就具备了运行的条件,一旦轮到它来享用CPU资源时,即JVM将CPU使用权切换给该线程时,此线程就可以脱离创建它的主线程独立开始自己的生命周期。

线程创建后仅仅是占有了内存资源,在JVM管理的线程中还没有这个线程,此线程必须调用start()方法通知JVM,这样JVM就会知道又有一个新线程排队等候切换了。

当JVM将CPU使用权切换给线程时,如果线程是Thread的子类创建的,该类中的run()方法就立即执行,run()方法规定了该线程的具体使命。所以程序必须在子类中重写父类的run()方法,Thread类中的run()方法没有具体内容。

在没有结束run()方法前,不要让线程再调用start()方法,否则会发生IIlegalThreadStateException异常。

3.中断

有四种原因的中断。

  • JVM将CPU资源从当前线程切换给其他线程,使本线程让出CPU的使用权处于中断状态。
  • 线程使用CPU资源期间,执行了sleep(int millsecond)方法,使当前线程进入休眠状态。sleep(int millsecond)方法是Thread类的一个类方法,线程一旦执行了sleep(int millsecond)方法,就立刻让出CPU的使用权,使当前线程处于中断状态。经过参数millsecond指定的毫秒之后,该线程就重新进到线程队列中排队等待CPU资源,以便从中断出继续运行。
  • 线程使用CPU资源期间,执行了wait()方法,使得当前线程进入等待状态。
  • 线程使用CPU资源期间,执行某个操作进入阻塞状态,比如执行读/写操作引起阻塞。进入阻塞状态时线程不能进入排队队列,只有当引起阻塞的原因消除时,线程才重新进到线程队列中排队等待CPU资源。

4.死亡

处于死亡状态的线程不具有继续运行的能力。

线程死亡的原因有二,一个是正常运行的线程完成了它的全部工作,即执行完run()方法中的全部语句,结束了run()方法;另一个原因是线程被强制性地终止,即强制run()方法结束。所谓死亡就是线程释放了实体,即释放分配给线程对象的内存。

代码展示如下所示:

public class Test05 {

    public static void main(String[] args) {
// TODO Auto-generated method stub
SpeakElephant speakElephant;
SpeakCar speakCar;
speakElephant = new SpeakElephant();
speakCar = new SpeakCar();
speakElephant.start();
speakCar.start();
for(int i = 1; i <= 15; i++)
{
System.out.print("主人" + i + " ");
}
} }

SpeakCar.java

public class SpeakCar extends Thread{
public void run()
{
for(int i = 0; i <= 20; i++)
{
System.out.print("轿车"+ i + " ");
}
}
}

SpeakElephant.java

public class SpeakElephant extends Thread{
public void run()
{
for(int i = 0; i <= 20; i++)
{
System.out.print("大象" + i + " ");
}
}
}

运行结果如下所示:

而且每次运行的结果都不一样,

线程调度与优先级

处于就绪的线程首先进入就绪队列等候CPU资源,同一时刻在就绪队列中的线程可能有很多个。Java虚拟机中的线程调度器负责管理线程,调度器把线程的优先级分为10个级别,分别用Thread类中的类常量表示。每个Java线程的优先级都在常数1和10之间。如果没有明确地设置好线程的优先级别,每个线程的优先级别都为常数5.

线程的优先级通过setPriority(int grade)方法调整,如果参数不在1和10之间,那么会产生异常。

review33的更多相关文章

  1. win10+Anaconda3+CUDA9.0+CUDNN7.1+TensorFlow-gpu1.9+Pycharm

    想在win10上运行下YOLO的例子,要先配置环境,折腾了两天,终于好了,整理下自己觉得有用且正确的流程. win10+Anaconda3+CUDA9.0+CUDNN7.1+TensorFlow1.9 ...

随机推荐

  1. TFS二次开发-基线文件管理器(5)-源码文件的读取

      在上一节中,我们在保存标签之前,已经将勾选的文件路径保存到了Listbox中,这里只需要将保存的数据输出去为txt文档就可以做版本控制了.   版本文件比较复杂的是如何读取,也就是如何通过文件路径 ...

  2. CSS伪类选择器active模拟JavaScript点击事件

    一.说明 设置元素在被用户激活(在鼠标点击与释放之间发生的事件)时的样式. IE7及更早浏览器只支持a元素的:active,从IE8开始支持其它元素的:active. 另:如果需要给超链接定义:访问前 ...

  3. C++程序设计练习(一)

    // 1. 在屏幕上输出内容 #include<iostream> using namespace std; int main(){ int i= 1; cout<<" ...

  4. python学习之路-第二天-常见的注意事项(代码风格、运算符、优先级、控制语句)

    总结了今天学习几个注意事项: 对代码声明变量的时候没必要像以前写java或者c代码要声明数据类型,只需要赋值即可 代码一行基本只写一句逻辑行,而且尽量不在python里面写':' 明确的行连接'',暗 ...

  5. 剑指offer 面试19题

    面试19题: 题目:正则表达式匹配 题:请实现一个函数用来匹配包括'.'和'*'的正则表达式.模式中的字符'.'表示任意一个字符,而'*'表示它前面的字符可以出现任意次(包含0次). 在本题中,匹配是 ...

  6. Django当中的sql查询

    十二:在Django中使用sql   关键字: connection     connections       transaction insert/create/update/delete/sel ...

  7. JavaScript:学习笔记(1)——在HTML中使用JS

    在HTML中使用JavaScript <script>元素 1.直接在网页中嵌入JS代码 说明: 请不要在代码的任何地方出现</script>字符串 这是由于解析嵌入式代码的规 ...

  8. PAT 天梯赛 L1-033. 出生年 【水】

    题目链接 https://www.patest.cn/contests/gplt/L1-033 AC代码 #include <cstdio> #include <cstring> ...

  9. 继承Thread类与实现Runnable接口

    java中创建线程有两种方式: 1. 类继承Thread类,重写run方法,每创建一个实例对象即开启一个线程 2. 类实现Runnable接口,重写run方法,将实例对象传入新建Thread的方法: ...

  10. HDU 4783 Clumsy Algorithm

    题意不提. 我们可以发现,可以将最终序列分为对于第i个位置i-pi>=0与i-pi<0种两个子序列.且如果f[n]==g[n],则有两个子序列都递增. 原因是f[n]表示1-n这个排列的逆 ...