一、多线程基础

编写线程程序主要是构造线程类。构造线程类的方式主要有两种,一种是通过构造类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. 8.1 EntityTypeConfiguration Class in Code-First【Code First系列】

    在我们学习Fluent API之前,先来看看Fluent API中重要的类--EntityTypeConfiguration吧. EntityTypeConfiguration类是Fluent API ...

  2. 10.Configure One-to-Many(配置一对多关系)【Code-First系列】

    现在,我们将学习怎么配置一对多的关系. Visit Entity Relationship section to understand how EF manages one-to-one, one-t ...

  3. deviceFilters与设备过滤

    本主题是ASP.NET在移动设备上展示的方面的内容 起初看起来deviceFilters与前面的browserCaps类似.同样也会关联到HttpBrowserCapabilities,而在这里用到的 ...

  4. 墙裂推荐4款js网页烟花特效

    以下是几款网页特效和一款软件: http://keleyi.com/keleyi/phtml/jstexiao/1.htm  http://keleyi.com/keleyi/phtml/jstexi ...

  5. oracle与sqlserver部分区别

    oracle和sqlserver的区别:1,执行修改操作要接commit,不然数据仅仅只是查看,并不是提交数据2,oracle不能使用select 字段 这种查看方式查看数据:3,oracle存储过程 ...

  6. python查找指定目录下所有文件,以及改文件名的方法

    一: os.listdir(path) 把path目录下的所有文件保存在列表中: >>> import os>>> import re>>> pa ...

  7. Python获取中国证券报最新资讯

    # -*- coding: utf-8 -*- import urllib from bs4 import BeautifulSoup from time import time from time ...

  8. 程序员用HTML5给女朋友制作的3D相册

    程序员给女朋友用HTML5制作的3D相册,使用鼠标拖拽,能看到3D旋转效果,点击相片,相片能放大,移近.程序员发挥自己的专长,这是那些不懂编程的人望尘莫及的.本相册使用了HTML5的画布技术,需要谷歌 ...

  9. JS操作未跨域iframe里的DOM

    这里简单说明两个方法,都是未跨域情况下在index.html内操作b.html内的 DOM. 如:index.html内引入iframe,在index内如何用JS操作iframe内的DOM元素? 先贴 ...

  10. angular源码分析:$compile服务——指令的编写

    这一期中,我不会分析源码,只是翻译一下"https://docs.angularjs.org/api/ng/service/$compile",当然不是逐字逐句翻译,讲解指令应该如 ...