Java基础知识笔记(四:多线程基础及生命周期)

时间:2022-08-25 23:35:57

一、多线程基础

编写线程程序主要是构造线程类。构造线程类的方式主要有两种,一种是通过构造类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指定新创建的线程的名称。

二、线程的生命周期

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

Java基础知识笔记(四:多线程基础及生命周期)

在正常的程序流程中,线程一般要经历新生态、就绪态、运行态和死亡态这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学习笔记&lpar;四&rpar;——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. DataGridView列的宽度、行的高度自动调整

    注意:DataGridView控件是从.NET Framework 2.0版本开始追加的. 介绍一下DataGridView列的宽度和行的高度,根据单元格或Header的内容(一般是内容全部被表示)自 ...

  2. spring发布和接收定制的事件&lpar;spring事件传播&rpar;

    spring发布和接收定制的事件(spring事件传播) 2012-12-26 20:05 22111人阅读 评论(2) 收藏 举报  分类: 开源技术(如Struts/spring/Hibernat ...

  3. Cocos2d-x第一个坑,NDK 编译环境

    这些天搭建windows cocos2d-x的环境,基本上崩溃到死.目前好转.终于可以编译通过: 生成模板工程:在cmd下进入cocos2d-x的主目录,D:\Android\cocos2d-x-2. ...

  4. MongDB主从复制、复制集

    主从复制比较简单,指定master.slave即可,其中master可写可读.slave只能读不能写.向master插入数据时,mongodb会自动将数据复制到slave节点.这样做的好处是读写分离, ...

  5. 【php】中【event】之实现方式

    这两天看了点事件机制,那么在php中,如何实现最简单的事件呢? 废话不多说,我们上代码. <?php class Event{ //事件名称 public $name; //存储hander p ...

  6. 【POJ】3630 Phone List

    静态字典树. #include <cstdio> #include <cstring> #include <cstdlib> #define MAXN 10005 ...

  7. 转 sort按照数据大小排序

    一般默认的sort都是按照字母的ASCII进行排序的,现在想按照数字的大小进行排序 这里有一个文件test,内容为: 8723    23423 321324  213432 23      234 ...

  8. Spring AOP With AspectJ

    一.AOP和拦截器 某些情况下,AOP和拦截器包括Filter能够实现同样的功能,一般都是请求即controller层的操作,这三个执行顺序为Filter>Interceptor>AOP, ...

  9. Centos7&period;4下用Docker-Compose部署WordPress

    前言 最近在学习Docker相关知识,通过阅读第一本Docker书后,正想着手实战用一下这个技术,但又不太敢直接在项目环境下动手.考虑足足三秒钟之后决定买个阿里云ECS搭建一个属于自己的基于Docke ...

  10. 使用 JavaScript 将网站后台的数据变化实时更新到前端

    问:难道只能设置定时器每隔一秒通过 Ajax 向后台请求数据来实现吗? 答: 1. nodejs的 http://socket.io 支持上述 李宏训 所说的三种方式,另外还支持 Flash Sock ...