java中的特殊文件、日志技术、多线程入门
1|0一,属性文件( .properties)
1|11,特殊文件概述(必会)
我们知道IO流是用来读数据,目的是为了获取其中的信息供我们使用,但是普通的txt文件是杂乱无章的,除非我们规定,自己写。虽然可以但是约束性不高。所以在java中就出现了一些文件,来供我们使用,也就是只要我们获取到了这样的文件,就可以通过固定的技术来获取其中的内容,得到我们想要的信息。
下面就来了解两种特殊的文本文件,一种是properties文件,一种是XML文件,下面一一的作介绍。
- 后缀为.properties的文件,称之为属性文件,它可以很方便的存储一些类似于键值对的数据。经常当做软件的配置文件使用。
- 而xml文件能够表示更加复杂的数据关系,比如要表示多个用户的用户名、密码、家乡、性别等。在后面,也经常当做软件的配置文件使用。
学习这两个文件的方法从几个方面出发:
- 了解它们的特点以及作用
- 学习使用程序读取他们里面的数据
- 学习使用程序把数据存储到这些文件中。
1|22,Properties属性文件
我们先学习Properties这种属性文件。首先我们要掌握属性文件的格式:
- 属性文件后缀以
.properties
结尾 - 属性文件里面的每一行都是一个键值对,键和值中间用 = 隔开。比如:
admin=123456
#
表示这样是注释信息,是用来解释这一行配置是什么意思。- 每一行末尾不要习惯性加分号,以及空格等字符;不然会把分号,空格会当做值的一部分。
- 键不能重复,值可以重复<是不是想到了什么集合 🙈 >
通过上面对属性文件的简单的介绍,我们看到了这些关键字,键值对,间不能重复,值可以重复。从这里是不是能够想到我们学习的集合。那么如果要是有个类能让我们处理properties文件就好了。
喊一声java天下第一,就有了这么一个类。Properties,用来操作properties文件。先看一下类图
可以看到Properties类实现了Map接口,那么肯定就具有map这个双列集合的功能。这样子学习起来就很明白了。
Properties核心作用?
Properties类的对象,用来表示属性文件,可以用来读取属性文件中的键值对。
在了解了他的结构之后就来学习Properties中独有的方法,我们也基本只用他独有的方法。
构造器 | 说明 |
---|---|
public Properties() | 用于构建Properties集合对象(空容器) |
常用方法 | 说明 |
---|---|
public void load(InputStream is) | 通过字节输入流,读取属性文件里的键值对数据 |
public void load(Reader reader) | 通过字符输入流,读取属性文件里的键值对数据 |
public String getProperty(String key) | 根据键获取值(其实就是get方法的效果) |
public Set |
获取全部键的集合(其实就是ketSet方法的效果) |
在学习了方法之后就来使用一下,来操作properties文件。使用步骤:
使用Properties往属性文件中写键值对:需要用到下面的几个方法
常用方法 | 说明 |
---|---|
public Object setProperty(String key, String value) | 保存键值对数据到Properties对象中去。 |
public void store(OutputStream os, String comments) | 把键值对数据,通过字节输出流写出到属性文件里去 |
public void store(Writer w, String comments) | 把键值对数据,通过字符输出流写出到属性文件里去 |
往属性文件中写文件的步骤如下:
运行之后的文件如下:
2|0二,XML文件
2|11,XMl文件概述
本质是一种数据的格式,可以用来存储复杂的数据结构,和数据关系。
XML是可扩展的标记语言,意思是它是由一些标签组成 的,而这些标签是自己定义的。本质上一种数据格式,可以用来表示复杂的数据关系。
XML文件有如下的特点:
- XML中的
<标签名>
称为一个标签或者一个元素,一般是成对出现的。 - XML中的标签名可以自己定义(可扩展),但是必须要正确的嵌套
- XML中只能有一个根标签。
- XML标准中可以有属性
- XML必须第一行有一个文档声明,格式是固定的
<?xml version="1.0" encoding="UTF-8"?>
- XML文件必须是以.xml为后缀结尾
XML示例如下:
上面XML文件中的数据格式是最为常见的,标签有属性、文本、还有合理的嵌套。XML文件中除了写以上的数据格式之外,还有一些特殊的字符不能直接写。
- 像
<,>,&
等这些符号不能出现在标签的文本中,因为标签格式本身就有<>,会和标签格式冲突。如果标签文本中有这些特殊字符,需要用一些占位符代替。
那么如果需要在文件中表示就需要,像下面一样来对特殊的符号做一个替换:
如果文本中出现了大量的特殊字符,且不想使用特殊字符替换,可以用CDATA区,格式如下:
在idea中的XML文件中输入大写的 CD 就会自动生成
那么XML在实际的开发中有什么作用呢?
在json还没有出现之前,作为一种特殊的数据结构,在网络中进行传输,但是后面就被json代替了,因为JSON效率更高,更好。
第二就是用在配置文件中,现在仍然在使用。也是我们以后常见的地方。
2|22,XMl解析1
我们有个一个这样的文本文件,那么我们应该怎样获取中间的数据呢?可以通过前面学习过的IO流,然后一点一点的去获取。但是可以发现十分的麻烦。
记住,如果代码想对来说比较的固定,都是一个套路的话,那么我们的前辈,必然封装过,我们只需要面向对象的调用他们的代码就可以。那么XML解析肯定也有,下面就有一个介绍。
其实有很多开源的,好用的XML解析框架,最知名的是DOM4J(第三方开发的)
由于DOM4J是第三方提供的,所以需要把第三方提供的Jar包导入到自己的项目中来,才可以使用。具体步骤如下:
①下载Dom4j框架,官网下载。
②在项目中创建一个文件夹:lib
③将dom4j-2.1.3.jar文件复制到 lib 文件夹
④在jar文件上点右键,选择 Add as Library -> 点击OK
⑤在类中导包使用
DOM4J解析XML文件的思想是:文档对象模型(意思是把整个XML文档、每一个标签、每一个属性都等都当做对象来看待)。Dowument对象表示整个XML文档、root表示根标签一个XML只有一个根
、Element对象表示标签(元素)、Attribute对象表示属性、标签中的内容就是文本。
构造器方法 | 说明 |
---|---|
public SAXReader() | 构建Dom4J的解析器对象 |
public Document read(String url) | 把XML文件读成Document对象 |
public Document read(InputStream is) | 通过字节输入流读取XML文件 |
方法名 | 说明 |
---|---|
Element getRootElement() | 获得根元素对象 |
有根得到Element对象,下面是Element类中的方法:
方法名 | 说明 |
---|---|
public String getName() | 得到元素名字 |
public List |
得到当前元素下所有子元素 |
public List |
得到当前元素下指定名字的子元素返回集合 |
public Element element(String name) | 得到当前元素下指定名字的子元素,如果有很多名字相同的返回第一个 |
public String attributeValue(String name) | 通过属性名直接得到属性值 |
public String elementText(子元素名) | 得到指定名称的子元素的文本 |
public String getText() | 得到文本 |
在dom4j中对元素的操作对象如下,记住图片的中的几个单词基本就会了解析。当然Element中还可以套element
2|34,XML 文件写入
其实这个dom4j中也有写入的方法,其实很没有必要,其实我们做一个字符串然后自己通过IO写入文件即可,不用在创建一堆类,调用一堆方法。我直接写不香吗?所以下一个知识点。
2|45,XML约束
如果自己亲自的去解析了这个文件,我们会发现,我们需要知道里面有几层标签,这样我们才有法遍历,要不然就是一个XML文件一个代码。那这不带累死。那么有没有一个办法去限制,XML中的内容呢?bing 狗, 当然。就是约束文件啦。
XML约束指的是限制XML文件中的标签或者属性,只能按照规定的格式写。
比如我在项目中,想约束一个XML文件中的标签只能写<书>、<书名>、<作者>、<售价>这几个标签,如果写其他标签就报错。
怎么才能达到上面的效果呢?有两种约束技术,一种是DTD约束<老技术>、一种是Schame约束<更新之后>。
- DTD约束案例
如下图所示book.xml中引入了DTD约束文件,book.xml文件中的标签就受到DTD文件的约束
DTD文件解释
- Schame约束案例
如下图所示,左边的book2.xml文件就受到右边schame文件(.xsd结尾的文件)的约束。我们也会发现这个文件可以是一个网址,所以就很方便。我们只需要知道我们应当,怎么做就可以了。
第二行中的xmlns 全称是xmlNameSpeace , 可以理解为和java中的import的功用一样,后面的xsi,可以认为是起的一个别名。
3|0三,日志技术
3|11,日志概述
想搞清楚什么是日志,可以通过下面几个问题来了解的。
- 系统系统能记住某些数据被谁操作,比如被谁删除了?
- 想分析用户浏览系统的具体情况,比如挖掘用户的具体喜好?
- 当系统在开发中或者上线后出现了Bug,崩溃了,该通过什么去分析,定位Bug?
而日志就可以帮我们解决以上的问题。所以日志就好比生活中的日记,日记可以记录生活中的点点滴滴;而程序中的日志,通常就是一个文件,里面记录了程序运行过程中产生的各种数据。
日志技术有如下好处
- 日志可以将系统执行的信息,方便的记录到指定位置,可以是控制台、可以是文件、可以是数据库中。
- 日志可以随时以开关的形式控制启停,无需侵入到源代码中去修改。
3|22,日志的体系
有很多日志框架给开发者使用。所谓日志框架就是由一些牛人或者第三方公司已经做好的实现代码,后来者就可以直接拿过去使用。
日志框架有很多种,比如有JUL(java.util.logging)、Log4j、logback等。但是这些日志框架如果使用的API方法都不一样的话,使用者的学习成本就很高。为了降低程序员的学习压力,行内提供了一套日志接口,然后所有的日志框架都按照日志接口的API来实现就可以了。
这样程序员只要会一套日志框架,那么其他的也就可以通过用,甚至可以在多套日志框架之间来回切换。比较常用的日志框架,和日志接口的关系如下图所示
下面就来学Logback日志框架,也是业界中使用最为广泛的。
Logback日志分为下面几个模块
3|33,Logback快速入门<必会>
由于Logback是第三方提供的技术,所以首先需要将Jar包引入到项目中,具体步骤如下
-
在网上找到
slftj-api.jar、logback-core.jar、logback-classes.jar
这三个jar包,复制一下 -
在当前模块下面新建一个lib文件夹,把刚刚复制的三个jar包都粘贴到此处
-
从资料中找到
logback.xml
配置文件,将此文件复制粘贴到src目录下(必须是src目录)也可以自己创建一个resource目录,但是要和src同级,并且右键选择下图的选项,这样idea就可以识别了,以后什么配置文件呀都在这。
-
然后就可以开始写代码了,在代码中创建一个日志记录日对象 <固定 >,通过LOGGER对象操作
logback.xml配置文件:
认识一下日志的五个级别:
日志级别指的是日志信息的类型,日志都会分级别,常见的日志级别如下(优先级依次升高):
日志级别 | 说明 |
---|---|
trace | 追踪,指明程序运行轨迹 |
debug | 调试,实际应用中一般将其作为最低级别,而 trace 则很少使用 |
info | 输出重要的运行信息,数据连接、网络连接、IO操作等等,使用较多 |
warn | 警告信息,可能会发生问题,使用较多 |
error | 错误信息, 使用较多 |
通过Logger对象直接调用对应的日志级别即可
示例代码如下:
当我们运行程序时,就可以看到控制台记录的日志:
会发现配置文件中配置路径中的log文件也会记录:
3|44,日志配置文件logback.xml
源文件在上面
作用: 对Logback日志框架进行控制的。
日志的输出位置、输出格式的设置:
通常可以设置2个输出日志的位置:一个是控制台、一个是系统文件中,通过name可以分别
开启日志(ALL),取消日志(OFF):
- 如下图所示,控制日志的输出的格式
日志格式是由一些特殊的符号组成,可以根据需要删减不想看到的部分。比如不想看到线程名那就不要[%thread]。但是不建议更改这些格式,因为这些都是日志很基本的信息。
3|55,配置日志的级别
关于日志的级别,在上面有说明。
那么在哪里配置日志级别呢?如下图所示
Logback只输出大于或者等于核心配置文件配置的日志级别信息。小于配置级别的日志信息,不被记录。
4|0四,多线程入门
什么是线程?
线程就是程序内部的一条执行通道。程序中如果只有一条执行通道,那这个程序就是单线程的程序。
那么什么是多线程呢?
多线程是指从软硬件上实现的多条执行流程的技术(多条线程由CPU负责调度执行)。
创建线程的方式有如下三种。常用第二种,但是各有各的好处。
4|11,线程创建方式1 -> 继承Thread类
具体步骤:
再定义一个测试类,在测试类中创建MyThread线程对象,并启动线程
打印结果如下图所示,我们会发现MyThread和main线程在相互抢夺CPU的执行权(注意:哪一个线程先执行,哪一个线程后执行,目前是无法控制的,每次输出结果都会不一样)
最后我们还需要注意一点:不能直接去调用run方法,如果直接调用run方法就不认为是一条线程启动了,而是把Thread当做一个普通对象,此时run方法中的执行的代码会成为主线程的一部分。此时执行结果是这样的。
4|22,线程创建方式2 -> 实现Runnable接口
Java为开发者提供了一个Runnable接口,该接口中只有一个run方法,意思就是通过Runnable接口的实现类对象专门来表示线程要执行的任务。具体步骤如下
代码如下:先准备一个Runnable接口的实现类
再写一个测试类,在测试类中创建线程对象,并执行线程
控制台输出结果:
4|33,线程创建方式2 之匿名内部类 和 Lambda表达式
关于匿名内部类和Lambda,在前面的笔记中都有记录,所以就不在赘述,直接使用
4|44,线程的创建3 -> 实现Callable接口
已经有两种了为什么还有要第三种呢? 这样,我们先分析一下前面两种都存在的一个问题。然后再引出第三种可以解决这个问题。
- 假设线程执行完毕之后有一些数据需要返回,前面两种方式重写的run方法均没有返回结果。
- JDK5提供了Callable接口和FutureTask类来创建线程,它最大的优点就是有返回值。在Callable接口中有一个call方法,重写call方法就是线程要执行的代码,它是有返回值的
第三种创建线程的方式,步骤如下
代码如下:先准备一个Callable接口的实现类
再定义一个测试类,在测试类中创建线程并启动线程,还要获取返回结果
再定义一个测试类,在测试类中创建线程并启动线程,还要获取返回结果
4|55,三种方式的优点和缺点
方式一优缺点:
-
优点: 编码简单
-
缺点: 线程类已经继承Thread,无法继承其他类,不利于功能的扩展。
方式二优缺点:
-
优点: 任务类只是实现接口,可以继续继承其他类、实现其他接口,扩展性强。
-
缺点: 需要多一个Runnable对象。
方式三优缺点:
-
优点: 线程任务类只是实现接口,可以继续继承类和实现接口,扩展性强;可以在线程执行完毕后去获取线程执行的结果。
-
缺点: 编码复杂一点。
4|66,Thread类常用的方法
Thread提供的常见构造器 | 说明 |
---|---|
public Thread(String name) | 可以为当前线程指定名称 |
public Thread(Runnable target) | 封装Runnable对象成为线程对象 |
public Thread(Runnable target, String name) | 封装Runnable对象成为线程对象,并指定线程名称 |
Thread提供的常用方法 | 说明 |
---|---|
public void run() | 线程的任务方法 |
public void start() | 启动线程 |
public String getName() | 获取当前线程的名称,线程名称默认是Thread-索引 |
public void setName (String name) | 为线程设置名称 |
public static Thread currentThread() | 获取当前执行的线程对象 |
public static void sleep(long time) | 让当前执行的线程休眠多少毫秒后,再继续执行 |
public final void join()... | 让调用当前这个方法的线程先执行完! |
下面演示一下getName()
、setName(String name)
、currentThread()
、sleep(long time)
,join()
这些方法的使用效果。
使用join之后的测试结果:也就是说,使用了join方法,就相当于让乌龟插了一个队,必须乌龟完事了兔子才可以运行,不存在并发。
有第一个小问题:就是start之后java做了什么?
Thread类还提供了诸如:yield、interrupt、守护线程、线程优先级等线程的控制方法,在开发中很少使用,这些方法会后续需要用到的时候再补充。
睡觉睡觉,明天继续学线程!加油加油!!!
__EOF__

本文链接:https://www.cnblogs.com/yfs1024/p/17201947.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角【推荐】一下。您的鼓励是博主的最大动力!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 25岁的心里话
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现