一、多线程基础

编写线程程序主要是构造线程类。构造线程类的方式主要有两种,一种是通过构造类java.lang.Thread的子类,另一种是通过构造方法实现接口java.lang.Runnable的类。因为类java.lang.Thread实际上也是实现了接口java.lang.Runnable的类,所以上面两种构造线程类的方法从本质上都是构造实现接口java.lang.Runnable的类。下面将具体介绍着两种方法。

(1)通过类Thread的子类构造线程

类java.lang.Thread的每个实例对象就是Java程序的一个线程,但是一般只能通过构造其子类的实例对象来实现。构造类java.lang.Thread的子类的主要目的是为了让线程类的实例对象能完成线程程序所需要的功能。

在编写类java.lang.Thread的子类的过程中,一个很重要的步骤就是编写run成员方法。这个成员方法实际上是对类java.lang.Thread的成员方法public void run()的覆盖。它包含了线程所需要执行的代码。虽然线程的执行代码在成员方法run中,但是启动或运行线程并不是直接调用成员方法run的,而是调用类java.lang.Thread的成员方法public void start()启动线程。

如果直接调用成员方法run,则一般来说会立即执行成员方法run,从而失去线程的特性。在调用成员方法start之后,Java虚拟机会自动启动线程,从而由Java虚拟机进一步统一调度线程,实现各个线程一起并发运行。Java虚拟机决定是否开始以及何时开始运行该线程,而线程的运行实际上就是执行线程的成员方法run。

(2)通过接口Runnable构造线程

Java语言的语法规定每个类只能有一个直接父类,所以通过接口java.lang.Runnable构造线程是在构造线程过程中可能出现的多重继承问题的一种解决方案。

通过接口java.lang.Runnable构造线程首先需要编写一个实现接口java.lang.Runnable的类。接口java.lang.Runnable只声明了唯一的成员方法void run(),因此,编写实现接口java.lang.Runnable的类的一般格式如下:

public class A extends B implements Runnable

{

//类体的其它部分

public void run()

{

成员方法run的方法体

}

//类体的其它部分

}

其中,A和B分别表示两个类的名称。在上面的格式中,“extends B”不是必须的,是否需要应当由具体需求而定。如果“extends B”是必须的,则通过接口java.lang.RUnnable构造线程的方法似乎是非常有必要的。因为类A已经有一个直接父类B,所以类A不能再是类java.lang.Thread的直接子类。借助于接口java.lang.Runnable可以避开这个问题。与通过构造类java.lang.Thread的子类创建线程的方法类似,由类A构造出来的线程的执行代码就封装在类A的成员方法run中。这里编写的run成员方法实现了对接口java.lang.Runnable的成员方法run的覆盖。

在编写玩实现接口java.lang.Runnable的类A之后,构造和启动线程的方法如下:

A  a = new A();

Thread  t = new Thread(a);

T.start();

(3)后台线程

线程可以分为后台线程和用户线程。后台线程在有些资料中也称为守护线程或精灵线程。它和用户线程的区别只是在于当在一个程序中只有后台线程在运行时,程序会立即退出。如果一个程序还存在正在运行的用户线程,则该程序不会中止。因此,后台线程通常用来为其他线程提供服务。在默认情况下,线程是用户线程。

一般通过类java.lang.Thread的成员方法public final boolean isDaemon()来判断一个线程是用户还是后台线程。通过类java,lang.Thread的成员方法public final void setDaemo(boolean on)可以将线程状态在用户线程和后台线程之间切换,在调用该方法时,一定要在public void start()方法被调用之前调用,否则将会报错。

(4)线程组

线程可以通过线程组(类java.lang.ThreadGroup的实例对象)来进行管理。这里的线程组是一些线程和线程组的集合。因为线程组可以包含其他线程组,所以线程组实际上形成了一个树状的体系结构。除了树状结构根部的线程组之外,每个线程组都有一个父线程组。一个线程组的父线程组就是包含该线程组的线程组。

构造线程组可以通过类java.lang.ThreadGroup的两个构造方法。其中,一个构造方法是:

public ThreadGroup(String name),它的参数name用来用来指定线程组的名称,这时构造出来的线程组的父线程组就是当前线程所在的线程组。

另一个构造方法是:

public ThreadGroup(ThreadGroup parent,String name),其中参数parent指定父线程组,参数name指定新构造的线程组的名称。

将一个线程添加到一个线程组中一般是在创建线程时通过线程的构造方法的参数指定线程组。例如,类java.lang.Thread的构造方法:

public Thread(ThreadGroup group,String name)的参数group指定所要添加到的线程组,参数name指定新创建的线程的名称。

二、线程的生命周期

线程的生命周期基本上如下图所示:

在正常的程序流程中,线程一般要经历新生态、就绪态、运行态和死亡态这4个基本状态。有时由于线程的并发等原因,还可能进入阻塞态。另外,根据程序的需要,线程还有可能进入等待态和睡眠态。

刚刚创建的线程还不能与其他线程一同并发运行。这时需要调用线程的成员方法start,使得线程进入就绪态。只有处于就绪态的线程才能参与Java虚拟机对线程的调度。Java虚拟机按照一定的调度规则让一些处于就绪态的线程进入运行态。进入运行态的线程自动执行在线程的成员方法public void run()中的代码。在执行run成员方法代码之后,线程自动进入死亡态。

Java虚拟机对线程的调度首先要根据线程的优先级。每个线程都有优先级。Java虚拟机规定所有线程最小的优先级大小为1,最大为10。

在线程调度的过程中,如果存在多个处于就绪态的线程,则优先级高的线程优先进入运行态。如果存在资源共享冲突,则优先级高的线程优先占用该资源。如果线程的优先级都一样,则Java虚拟机随机调度这些线程进入运行运行态或占用资源。如果多个线程共享资源,并且只能有限个线程同时占用该资源,则Java虚拟机在调度就绪态的线程时会让一些处于就绪态的线程占用这些资源,而其他处于就绪态的线程就会因为资源短缺而自动进入阻塞态。处于阻塞态的线程在所需要的资源准备就绪(例如其他线程退出这些资源)时会自动重新进入就绪态,再次由Java虚拟机进行调度。

Java基础知识笔记(四:多线程基础及生命周期)的更多相关文章

  1. Java精选笔记_多线程(创建、生命周期及状态转换、调度、同步、通信)

    线程概述 在应用程序中,不同的程序块是可以同时运行的,这种多个程序块同时运行的现象被称作并发执行. 多线程可以使程序在同一时间内完成很多操作. 多线程就是指一个应用程序中有多条并发执行的线索,每条线索 ...

  2. Android(java)学习笔记170:Activity的生命周期

    1.首先来一张生命周期的总图: onCreate():创建Acitivity界面       onStart():让上面创建的界面可见              onResume():让上面创建的界面 ...

  3. Android(java)学习笔记113:Activity的生命周期

    1.首先来一张生命周期的总图: onCreate():创建Acitivity界面       onStart():让上面创建的界面可见              onResume():让上面创建的界面 ...

  4. CSS基础知识笔记(四)

    元素分类 标签元素大体被分为三种不同的类型:块状元素.内联元素(又叫行内元素)和内联块状元素. 常用的块状元素有: <div>.<p>.<h1>...<h6& ...

  5. Android(java)学习笔记65:线程的生命周期

    1. 我们学习线程本质就是学习如何开始线程和终止线程.下面这个关于线程的生命周期图,要牢记: 新建状态:当程序使用new关键字创建了一个线程之后,该线程就处于新建状态.此时和其他Java对象一样,它仅 ...

  6. Android(java)学习笔记5:线程的生命周期

    1. 我们学习线程本质就是学习如何开始线程和终止线程.下面这个关于线程的生命周期图,要牢记: 新建状态:当程序使用new关键字创建了一个线程之后,该线程就处于新建状态.此时和其他Java对象一样,它仅 ...

  7. iOS学习笔记(四)——iOS应用程序生命周期

    开发应用程序都要了解其生命周期,开始接触android时也是从应用程序生命周期开始的,android的应用程序生命周期更多是其组件的生命周期,例如Activity.Service.今天我们接触一下iO ...

  8. spring in action 学习笔记四:bean的生命周期

    bean 的生命周期分为:一个是ApplicationContext的容器的bean的生命周期,另一个是BeanFactory容器的生命周期. 首先介绍一下:ApplicationContext的容器 ...

  9. Java多线程基础知识笔记(持续更新)

    多线程基础知识笔记 一.线程 1.基本概念 程序(program):是为完成特定任务.用某种语言编写的一组指令的集合.即指一段静态的代码,静态对象. 进程(process):是程序的一次执行过程,或是 ...

  10. Java IO学习笔记四:Socket基础

    作者:Grey 原文地址:Java IO学习笔记四:Socket基础 准备两个Linux实例(安装好jdk1.8),我准备的两个实例的ip地址分别为: io1实例:192.168.205.138 io ...

随机推荐

  1. 企业 SOA 设计(2)–组件化产品开发平台

    上一篇<企业 SOA 设计(1)–ESB 设计>中,写到我们的 SOA 设计分为两个层面来进行:一个是系统间的 SOA 设计,主要通过 ESB 来完成:另一方面则是单个应用系统内部的 SO ...

  2. C# EPL USB 指令打印

    private void btnPrinter_Click(object sender, EventArgs e) { #region ESC 热敏图像点阵像素点读取打印 //Bitmap bitma ...

  3. webapi文档描述-swagger

    最近做的项目使用mvc+webapi,采取前后端分离的方式,后台提供API接口给前端开发人员.这个过程中遇到一个问题后台开发人员怎么提供接口说明文档给前端开发人员,最初打算使用word文档方式进行交流 ...

  4. CSS3点赞动画特效源码下载

    体验效果:http://hovertree.com/texiao/jquery/62/ 效果图: 下载:http://hovertree.com/h/bjaf/1dvh9ym6.htm 特效库:htt ...

  5. 10个调试Java的技巧

    调试不仅可以查找到应用程序缺陷所在,还可以解决缺陷.对于Java程序员来说,他们不仅要学会如何在Eclipse里面开发像样的程序,更需要学会如何调试程序.本文介绍了Java程序员必知的10个调试技巧, ...

  6. Artificial intelligence(AI)

    ORM: https://github.com/sunkaixuan/SqlSugar 微软DEMO: https://github.com/Microsoft/BotBuilder 注册KEY:ht ...

  7. Mule入门基础

    Mule入门文档 零.前提 在按照本文进行操作之前,假设您的系统已经具备以下前提: 已经安装了Sun公司的JDK1.4或JDK5.0版本,推荐使用JDK5.0. 正确设置了JAVA_HOME环境变量到 ...

  8. 一台主机上安装多个Tomcat

    1. 下载解压版的Tomcat,并解压两次,分别命名为Tomcat_Server_01和Tomcat_Server_02: 2. 进入Tomcat_Server_01\bin目录,编辑service文 ...

  9. php实现hack中的Shape特性

    用php进行静态类型编程,估计是我的一个心结. 依次有几篇文章都记录了我的一些探索: 通过指定函数/方法形参类型提高PHP代码可靠性 http://www.cnblogs.com/x3d/p/4285 ...

  10. 流的文件操作(File)

    一.流的分类: 1.流按照方向分类:分为输入流和输出流,流的操作是相对于内存而言. 输入流的定义:当我们从数据源中将数据读取到内存中就称为输入流,也叫读取流. 输出流的定义:当我们将内存中处理好的数据 ...