Java第二十章课堂总结

如果一次只完成一件事情,很容易实现。但现实生活中,很多事情都是同时进行的。Java中为了模拟这种状态,引入了线程机制。简单地说,当程序同时完成多件事情时,就是所谓的多线程。多线程应用相当广泛,使用多线程可以创建窗口程序、网络程序等。

20.1 线程简介
世间有很多工作都是可以同时完成的。例如,人体可以同时进行呼吸、血液循环、思考问题等活动;用户既可以使用计算机听歌,也可以使用它打印文件。同样,计算机完全可以将多种活动同时进行,这种思想放在Java中被称为并发,而将并发完成的每一件事情称为线程。

在Java中,并发机制非常重要。在以往的程序设计中,我们都是一个任务完成后再进行下一个任务,这样下一个任务的开始必须等待前一个任务的结束。Java语言提供了并发机制,程序员可以在程序中执行多个线程,每一个线程完成一个功能,并与其他线程并发执行,这种机制被称为多线程。然而,有必要强调的是,并不是所有编程语言都支持多线程。

Windows操作系统是多任务操作系统,它以进程为单位。一个进程是一个包含有自身地址的程序,每个独立执行的程序都称为进程。也就是说每个正在执行的程序都是一个进程。系统可以分配给每个进程一段有限的使用CPU的时间(也可以称为CPU时间片),CPU在这段时间中执行某个进程,然后下一个时间片又跳至另一个进程中去执行。由于CPU转换较快,所以使得每个进程好像是同时执行一样。

一个线程则是进程中的执行流程,一个进程中可以同时包括多个线程,每个线程也可以得到一小段程序的执行时间,这样一个进程就可以具有多个并发执行的线程。在单线程中,程序代码按调用顺序依次往下执行。如果需要一个进程同时完成多段代码的操作,就需要使用多线程。

20.2 创建线程
在Java中,主要提供两种方式实现线程,分别为继承java.lang.Thread类与实现java.lang.Runnable接口。本节将着重讲解这两种实现线程的方式。

20.2.1 继承Thread类
Thread类是java.lang包中的一个类,从这个类中实例化的对象代表线程,程序员启动一个新线程需要建立Thread实例。Thread类中常用的两个构造方法如下:

public Thread():创建一个新的线程对象。
public Thread(String threadName):创建一个名称为threadName的线程对象。
继承Thread类创建一个新的线程的语法如下:

public class ThreadTest extends Thread{}
完成线程真正功能的代码放在类的run()方法中,当一个类继承Thread类后,就可以在该类中覆盖run()方法,将实现该线程功能的代码写入run()方法中,然后调用Thread类中的start()方法执行线程,也就是调用run()方法。

Thread对象需要一个任务来执行,任务是指线程在启动时执行的工作,该工作的功能代码被写在run()方法中。run()方法必须使用以下语法格式:

public void run(){}
注意

如果start()方法调用一个已经启动的线程,系统将抛出IllegalThreadStateException异常。

当执行一个线程程序时,就自动产生一个线程,主方法正是在这个线程上运行的。当不再启动其他线程时,该程序就为单线程程序,如本章以前的程序都是单线程程序。主方法线程启动由Java虚拟机负责,程序员负责启动自己的线程

在main()方法中,使线程执行需要调用Thread类中的start()方法,start()方法调用被覆盖的run()方法,如果不调用start()方法,线程永远都不会启动,在主方法没有调用start()方法之前,Thread对象只是一个实例,而不是一个真正的线程。

20.2.2 实现Runnable接口
到目前为止,线程都是通过扩展Thread类来创建的,如果程序员需要继承其他类(非Thread类),而且还要使当前类实现多线程,那么可以通过Runnable接口来实现。例如,一个扩展JFrame类的GUI程序不可能再继承Thread类,因为Java语言中不支持多继承,这时该类就需要实现Runnable接口使其具有使用线程的功能。实现Runnable接口的语法如下:

public class Thread extends Object implements Runnable
说明

有兴趣的读者可以查询API,从中可以发现,实质上Thread类实现了Runnable接口,其中的run()方法正是对Runnable接口中的run()方法的具体实现。

实现Runnable接口的程序会创建一个Thread对象,并将Runnable对象与Thread对象相关联。Thread类中有以下两个构造方法:

public Thread(Runnable target)。
public Thread(Runnable target,String name)。
这两个构造方法的参数中都存在Runnable实例,使用以上构造方法就可以将Runnable实例与Thread实例相关联

使用Runnable接口启动新的线程的步骤如下:

(1)建立Runnable对象。

(2)使用参数为Runnable对象的构造方法创建Thread实例。

(3)调用start()方法启动线程。

通过Runnable接口创建线程时,程序员首先需要编写一个实现Runnable接口的类,然后实例化该类的对象,这样就建立了Runnable对象;接下来使用相应的构造方法创建Thread实例;最后使用该实例调用Thread类中的start()方法启动线程。

线程最引人注目的部分应该是与Swing相结合创建GUI程序,下面演示一个GUI程序,该程序实现了图标滚动的功能。

注意

启动一个新的线程,不是直接调用Thread子类对象的run()方法,而是调用Thread子类的start()方法,Thread类的start()方法产生一个新的线程,该线程运行Thread子类的run()方法。

20.3 线程的生命周期
线程具有生命周期,其中包含7种状态,分别为出生状态、就绪状态、运行状态、等待状态、休眠状态、阻塞状态和死亡状态。出生状态就是线程被创建时处于的状态,在用户使用该线程实例调用start()方法之前线程都处于出生状态;当用户调用start()方法后,线程处于就绪状态(又被称为可执行状态);当线程得到系统资源后就进入运行状态。

一旦线程进入可执行状态,它会在就绪与运行状态下转换,同时也有可能进入等待、休眠、阻塞或死亡状态。当处于运行状态下的线程调用Thread类中的wait()方法时,该线程便进入等待状态,进入等待状态的线程必须调用Thread类中的notify()方法才能被唤醒,而调用notifyAll()方法可将所有处于等待状态下的线程唤醒;当线程调用Thread类中的sleep()方法时,则会进入休眠状态。如果一个线程在运行状态下发出输入/输出请求,该线程将进入阻塞状态,在其等待输入/输出结束时线程进入就绪状态,对于阻塞的线程来说,即使系统资源空闲,线程依然不能回到运行状态。当线程的run()方法执行完毕时,线程进入死亡状态。

说明

使线程处于不同状态下的方法会在20.4节中进行讲解,在此读者只需了解线程的多个状态即可。

虽然多线程看起来像同时执行,但事实上在同一时间点上只有一个线程被执行,只是线程之间切换较快,所以才会使人产生线程是同时进行的假象。在Windows操作系统中,系统会为每个线程分配一小段CPU时间片,一旦CPU时间片结束就会将当前线程换为下一个线程,即使该线程没有结束。

要使线程处于就绪状态,有以下几种方法:

调用sleep()方法。
调用wait()方法。
等待输入/输出完成。

当线程处于就绪状态后,可以用以下几种方法使线程再次进入运行状态:

线程调用notify()方法。
线程调用notifyAll()方法。
线程调用interrupt()方法。
线程的休眠时间结束。
输入/输出结束。

20.4 操作线程的方法
操作线程有很多方法,这些方法可以使线程从某一种状态过渡到另一种状态。
 

20.4.1 线程的休眠
一种能控制线程行为的方法是调用sleep()方法,sleep()方法需要一个参数用于指定该线程休眠的时间,该时间以毫秒为单位。在前面的实例中,已经演示过sleep()方法,它通常是在run()方法内的循环中被使用。sleep()方法的语法如下:

 上述代码会使线程在2秒之内不会进入就绪状态。由于sleep()方法的执行有可能抛出InterruptedException异常,所以将sleep()方法的调用放在try-catch块中。虽然使用了sleep()方法的线程在一段时间内会醒来,但是并不能保证它醒来后进入运行状态,只能保证它进入就绪状态。
 

在本实例中定义了getC()方法,该方法用于随机产生Color类型的对象,并且在产生线程的匿名内部类中使用getGraphics()方法获取Graphics对象,使用该对象调用setColor()方法为图形设置颜色。调用drawLine()方法绘制一条线段,同时线段会根据纵坐标的变化自动调整。 

20.4.2 线程的加入
如果当前某程序为多线程程序,假如存在一个线程A,现在需要插入线程B,并要求线程B先执行完毕,然后再继续执行线程A,此时可以使用Thread类中的join()方法来完成。这就好比此时读者正在看电视,突然有人上门收水费,读者必须付完水费后才能继续看电视。

当某个线程使用join()方法加入另外一个线程时,另一个线程会等待该线程执行完毕后再继续执行。下面来看一个使用join()方法的实例。
 

在本实例中同时创建了两个线程,这两个线程分别负责进度条的滚动。在线程A的run()方法中使线程B的对象调用join()方法,而join()方法使当前运行线程暂停,直到调用join()方法 的线程执行完毕后再执行,所以线程A等待线程B执行完毕后再开始执行,即下面的进度条滚动完毕后上面的进度条才开始滚动。

20.4.3 线程的中断
以往有的时候会使用stop()方法停止线程,但当前版本的JDK早已废除了stop()方法,不建议使用stop()方法来停止一个线程的运行。现在提倡在run()方法中使用无限循环的形式,然后使用一个布尔型标记控制循环的停止。

如果线程是因为使用了sleep()或wait()方法进入了就绪状态,可以使用Thread类中interrupt()方法使线程离开run()方法,同时结束线程,但程序会抛出InterruptedException异常,用户可以在处理该异常时完成线程的中断业务处理,如终止while循环。

下面的实例演示了某个线程使用interrupted()方法,同时程序抛出了InterruptedException异常,在异常处理时结束了while循环。在项目中,经常在这里执行关闭数据库连接和关闭Socket连接等操作。
 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/234181.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【bug日记】如何切换jdk版本,如何解决java和javac版本不一致

背景 今天在安装jenkins后,使用java运行war包的时候,提示jdk1.8版本太低,需要提高版本,所以就需要切换jdk版本 解决 在用户变量中,首先更改了JAVA_HOME的地址为17的目录,发现javac的版本改为17了&#x…

Jmeter的接口测试详细步骤并实现业务闭环

一、首先是了解Jmeter接口测试用到的组件 1、测试计划:Jmeter的起点和容器2、线程组:代表一定的虚拟用户3、取样器:发送请求的最小单元4、逻辑控制器:控制组件的执行顺序5、前置处理器:在请求之前的操作6、后置处理器…

用sqlite制作对局记录管理

1. sqlite简介 sqlite是一款非常轻便小巧的数据库,以C语言开发,已流行了数十年,据说是世界上部署最多的数据库。为什么是部署最多的呢?因为它根本不需要数据库服务器,且可以在任意设备、任意操作系统上部署。因此&…

服务宕机、线上环境内存溢出OOM分析思路

前言 平时工作中,肯定会遇到哪个产品经理突然来找,说服务器又挂了,怎么又用不了啦!类似的紧急情况,遇到这种情况不要慌,我提供以下几点紧急补救思路。 1)重启大法保命 2)确认是否新…

5分钟上手浏览器插件测试——Eolink Apikit

Eolink Apikit 研发管理和自动化测试产品中,提供了多种发起 API 测试的方式: 服务器测试:通过 Eolink Apikit 官方远程服务器发送请求,不需要安装任何插件,但是无法访问本地服务器(localhost)、内网、局域网。插件测试…

Qt中,将一个结构体转为qbytearray后,如何将这个qpqbytearray重新恢复为之前的结构体

在 Qt 中,如果你有一个自定义的结构体,并将其转换为 QByteArray,然后想要将 QByteArray 转换回原始的结构体,你可以使用 Qt 的 QDataStream 类来实现这个转换过程。 首先,假设你有一个自定义的线段结构体如下&#xf…

Git Status 中文乱码解决

中文的文件名,全是乱码 解决: git config --global core.quotepath false

年终汇报这么写,升值加薪必有你!

#01 你这么能干, 老板知道吗? — 打工人最怕什么? 最怕你忙前忙后,干活一大堆,气出一身结节,锅还没少背,最后升职加薪没有你,出国旅游不带你;更怕你日常996&#xf…

基于深度学习的图像分割

摘要 遥感图像分割是利用遥感技术获取的高分辨率图像进行像素级别的分类,将图像中的不同物体或不同地物提取出来的过程。这个过程对于遥感应用具有重要意义,因为它能够提取出地物和地表特征,如河流、道路、建筑、植被、水体等,并且…

同义词替换器降低论文重复率的最新技术动态

大家好,今天来聊聊同义词替换器降低论文重复率的最新技术动态,希望能给大家提供一点参考。 以下是针对论文重复率高的情况,提供一些修改建议和技巧,可以借助此类工具: 标题:同义词替换器降低论文重复率的最…

从旺店通·企业版到金蝶云星空通过接口配置打通数据

从旺店通企业版到金蝶云星空通过接口配置打通数据 对接系统:旺店通企业版 旺店通是北京掌上先机网络科技有限公司旗下品牌,国内的零售云服务提供商,基于云计算SaaS服务模式,以体系化解决方案,助力零售企业数字化智能化…

MySQL数据库知识点简易总结篇

SQL数据库简易版笔记 SQL(结构化查询语句):可操作世界上所有的关系型数据 关系数据库 建立在关系模型基础上的数据库。简单来说,关系型数据库是多张能互相连接的二维表组成的数据库。其优势有: 都是表结构&#xf…

基于SSM的视康眼镜网店销售系统

末尾获取源码 开发语言:Java Java开发工具:JDK1.8 后端框架:SSM 前端:Vue 数据库:MySQL5.7和Navicat管理工具结合 服务器:Tomcat8.5 开发软件:IDEA / Eclipse 是否Maven项目:是 目录…

HarmonyOS4.0从零开始的开发教程20三方库的基本使用

HarmonyOS(十八)三方库的基本使用 三方库概述 三方库是开发者在系统能力的基础上进行了一层具体功能的封装,对其能力进行拓展,提供更加方便的接口,提升开发效率的工具。如果是发布到开源社区,称为开源三方…

高级算法设计与分析(二) -- 递归与分治策略

系列文章目录 高级算法设计与分析(一) -- 算法引论 高级算法设计与分析(二) -- 递归与分治策略 高级算法设计与分析(三) -- 动态规划 未完待续【 高级算法设计与分析(四) -- 贪…

CCD相机和CMOS相机有什么区别

问题描述:CCD相机和CMOS相机有什么区别。在阅读一些论文时,常看到工业上的检测常用到CCD相机,和我们熟知的CMOS相机有什么区别呢。 问题解答: CCD相机: 原理: 光电转换: 光子被感光芯片上的…

面试经典150题(32-37)

leetcode 150道题 计划花两个月时候刷完,今天(第十五天)完成了6道(32-37)150: 今天刚好有点没精神的感觉,然后碰到的题也不难。。天意!!! 32.(289. 生命游戏&#xff0…

iEnglish:家校协同培养学生自主阅读习惯

近日,2023年最新一期365天和1000天“iEnglish学习成长营”顺利结营。据悉,截至今年12月,在家庭场景中完成365天和1000天不间断阅读人数分别突破15万人和2万人。 近年来,全民终身学习的学习型社会不断深入推进,基础教育中对于学生的综合阅读能力素养新要求不断更新。提升孩子的…

【Git】Git基本操作

文章目录 Git 是什么Git 的优点Git 安装Linux UbuntuLinux CentOsWindows Git 基本操作1. 创建 Git 本地仓库2. 配置 Git3. Git工作区、暂存区和版本库4. 添加文件5. 查看 .git 文件6. 修改文件7. 版本回退 Git 是什么 Git是一个免费的、开源的分布式版本控制系统,…

【Linux】ip命令使用

ip命令 用于管理与配置网络接口和路由表。 ip命令的安装 ip 命令来自 iproute2 软件包,在 CentOS 7 中默认已安装。 yum install -y iproute 语法 ip [ OPTIONS ] OBJECT { COMMAND | help }ip [ -force ] -batch filename选项及作用 执行令 : ip …