首页 > 编程语言 >【Java学习】配置文件&日志&多线程

【Java学习】配置文件&日志&多线程

时间:2024-09-08 21:55:06浏览次数:10  
标签:Java String 配置文件 Thread 线程 new 日志 多线程 public

一、配置文件

1、概述

在企业开发过程中,我们习惯把一些需要灵活配置的数据放在一些文本文件中,而不是在Java代码写死。我们把这种存放程序配置信息的文件,统称为配置文件。配置文件一般要求有明确的格式,以方便读写操作。

2、Properties

Properties是一个Map集合(键值对集合),但是一般不会当集合使用。

核心作用:Properties是用来代表属性文件的,通过Properties可以读写 .properties属性文件里的内容。

 .properties属性文件中每一行都是一个键值对,用=或者空格隔开,且键不能重复,值可以。

使用Properties读取属性文件里的键值对数据:

使用Properties把键值对数据写出到属性文件里去:

示例代码:

public class Demo1 {
    public static void main(String[] args) throws Exception {
        //1. 创建一个配置文件对象
        Properties properties = new Properties();
        //2. 读取
        properties.load(new FileReader("code-10/user.properties"));
        String pwd = properties.getProperty("admin");
        System.out.println("admin");
        System.out.println(pwd);
        //3. 写出

        Properties prop2 = new Properties();

        prop2.setProperty("王五", "123456");
        prop2.setProperty("zhaoliu", "123好好好");

        prop2.store(new FileWriter("code-10/user.properties"), "这是从程序写入的文字");
    }
}

 

3、XML

XML全称Extensible Markup Language, 可扩展标记语言;

本质是一种数据的格式,可以用来存储复杂的数据结构,和数据关系。

特点:

1.XML中的“<标签名>” 称为一个标签或一个元素,一般是成对出现的。

2.XML中的标签名可以自己定义(可扩展),但必须要正确的嵌套。

3.XML中只能有一个根标签。

4.XML中的标签可以有属性。

5.XML文件的后缀名为:xml,文档声明必须是第一行。

<?xml version="1.0" encoding="UTF-8" ?>

version:XML默认的版本号码、该属性是必须存在的

encoding:本XML文件的编码

6.XML中可以定义注释信息:<!–- 注释内容 -->,快捷键是Ctrl+shift+/。

7.XML中书写”<”、“&”等,可能会出现冲突,导致报错,此时可以用如下特殊字符替代

&lt;    <  小于

&gt;    >  大于

&amp;   &  和号

&apos;  '  单引号

&quot;  "  引号 

 XML中可以写一个叫CDATA的数据区: <![CDATA[   …内容…  ]]>,里面的内容可以随便写。直接输入CD,就会有提示

<![CDATA[
    这里面随便输入        
]]>

解析XML文件:

  • 最知名的好用的解析XML的框架是:Dom4j(第三方研发的)

Dom4j解析XML-得到Document对象

SAXReader:Dom4j提供的解析器,可以认为是代表整个Dom4j框架

Document

Element提供的方法:

 

示例代码:

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.util.ArrayList;
import java.util.List;

public class Demo2_2 {
    public static void main(String[] args) throws FileNotFoundException, DocumentException {
        ArrayList<User1> userList = new ArrayList<>();//创建存储User1对象的list集合(最下面要用的)

        //1、将dom4j的jar包加入到项目中

        //2、创建DOM4]解析器对象SAXReader
        SAXReader saxReader = new SAXReader();
        //3、获取Document文档对象,获取根标签对象
        //Document的对象看似是只获得了根标签(root标签),其实已经包含了所有的子标签
        Document document = saxReader.read(new FileReader("day0908-10/b-2.xml"));
        //4、从根标签对象开始往下层层解析
        Element rootElement = document.getRootElement();
        //获取根标签的名字
        String rootElementName = rootElement.getName();
        //获取根标签下的所有子标签
        List<Element> elements = rootElement.elements();
        System.out.println(elements.size());

        //遍历拿到的标签集合elements
        for (Element element : elements) {
            System.out.println("=============");

            String name = element.element("name").getText();//获取name标签的内容并得到文本内容
            System.out.println("name="+name);

            String password = element.elementText("password");
            System.out.println("password:"+password);

            String address = element.elementText("address");
            System.out.println("address:" + address);

            String gender = element.elementText("gender");
            System.out.println("gender:" + gender);

            User1 user1 = new User1(name, password, address, gender);


            userList.add(user1);
        }
        for (User1 user1 : userList) {
            System.out.println(user1);
        }


    }
}

class User1 {
    private String name;
    private String password;
    private String address;
    private String gender;

    public User1() {
    }

    public User1(String name, String password, String address, String gender) {
        this.name = name;
        this.password = password;
        this.address = address;
        this.gender = gender;
    }

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", password='" + password + '\'' +
                ", address='" + address + '\'' +
                ", gender='" + gender + '\'' +
                '}';
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public String getGender() {
        return gender;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }
}

 

二、日志技术

 1、概述

程序中的日志,通常就是一个文件,里面记录的是程序运行过程中的各种信息。

我们在初学Java的时候经常用到的输出语句System.out.println()所输出的内容就可以看作是一种日志,但是输出语句有许多弊端:

  • 日志会展示在控制台
  • 不能更方便的将日志记录到其他的位置(文件,数据库)
  • 想取消日志,需要修改源代码才可以完成

在实际项目开发中就会使用日志技术,可以将系统执行的信息,方便的记录到指定的位置(控制台、文件中、数据库中)。也可以随时以开关的形式控制日志的启停,无需侵入到源代码中去进行修改。

日志技术的体系结构:

  • 日志接口:设计日志框架的一套标准,日志框架需要实现这些接口。
  • 日志框架:大佬或者第三方公司已经做好的实现代码,后来者直接可以拿去使用。
  • 注意1:因为对Commons Logging接口不满意,有人就搞了SLF4J;因为对Log4j的性能不满意,有人就搞了Logback。
  • 注意2:Logback是基于slf4j的日志规范实现的框架。

使用Logback日志框架,至少需要在项目中整合slf4j-api日志接口、logback-core核心模块、logback-classic API模块。

 2、Logback

使用Logback日志框架的步骤:

1.导入Logback框架到项目中去。(slf4j-api日志接口、logback-core核心模块、logback-classic API模块)

2.将Logback框架的核心配置文件logback.xml直接拷贝到src目录下(必须是src下)

3.创建Logback框架提供的Logger对象,然后用Logger对象调用其提供的方法就可以记录系统的日志信息

public static final Logger LOGGER = LoggerFactory.getLogger("当前类类名");

核心配置文件logback.xml 

对Logback日志框架进行控制的,通常可以设置2个输出日志的位置:一个是控制台、一个是系统文件中:

<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">

<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">

开启日志(ALL),取消日志(OFF)

<root level="ALL">    

        <appender-ref ref="CONSOLE"/>    

        <appender-ref ref="FILE" />

</root> 

ALL 和 OFF分别是打开全部日志和关闭全部日志。 

3、Logback设置日志级别

日志级别指的是日志信息的类型,日志都会分级别,常见的日志级别如下(优先级依次升高):

<root level=“info">

        <appender-ref ref="CONSOLE"/>

        <appender-ref ref="FILE" />

</root>

只有日志的级别是大于或等于核心配置文件配置的日志级别,才会被记录,否则不记录。

示例代码:

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class Demo1 {
    public static final Logger LOGGER = LoggerFactory.getLogger("Demo1");

    public static void main(String[] args) {
        LOGGER.debug("程序开始");

        div(1,0);
    }

    public static int div(int a, int b) {
        LOGGER.debug("方法执行了,a={},b={}",a,b);
        try {
            int c = a/b;
            return c;
        }catch (Exception e) {
            LOGGER.error("{}/{} 出错了",a,b);
            e.printStackTrace();
            throw new RuntimeException("好好好");
        }
    }
}

三、多线程

1、概述

什么是线程:

  • 线程:简单的说,就是计算机在做一件事
  • 单线程:在计算机中同一时间只能做一件事
  • 多线程:在计算机中同一时间可以做多件事

多线程的主要好处有:减少队列阻塞带来的影响、提高CPU的利用率。

2、线程的创建方式

(1)继承Thread类

  • 定义一个子类继承线程类java.lang.Thread,重写run()方法
  • 创建子类的对象
  • 调用子类对象的start()方法启动线程(底层会自动去执行run方法)        

优缺点:

优点:编码简单

缺点:线程类已经继承Thread,无法继承其他类,不利于功能的扩展。

示例代码:

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class Demo1 {
    public static final Logger LOGGER = LoggerFactory.getLogger("Demo1");
    public static void main(String[] args) {
        LOGGER.info("程序开始");
        //需求:创建两个线程,分别用于打印10个A和10个B,最后观察下输出顺序
        
        //创建子类的对象
        AThread aThread = new AThread();
        BThread bThread = new BThread();

        //调用子类对象的start()方法启动线程(底层会自动去执行run方法)
        aThread.start();
        bThread.start();
    }
}

/**
 * 定义一个子类继承线程类java.lang.Thread,重写run()方法
 */
class AThread extends Thread {
    public static final Logger LOGGER = LoggerFactory.getLogger("AThread");
    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            LOGGER.debug("AThread-A{}", i );
        }
    }
}
/**
 * 定义一个子类继承线程类java.lang.Thread,重写run()方法
 */
class BThread extends Thread {
    public static final Logger LOGGER = LoggerFactory.getLogger("BThread");
    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            LOGGER.debug("BThread-B{}", i );
        }
    }
}

创建两个分别继承了Thread的类,main方法中创建这两个类的对象,然后对象之间调用start()方法即可实现多线程启动。

注意事项:

1.启动线程必须是调用start方法,不是调用run方法

  • 直接调用run方法会当成普通方法执行,此时相当于还是单线程执行
  • 只有调用start方法才是启动一个新的线程执行
  • 这样主线程一直是先跑完的,相当于是一个单线程的效果了

2.不要把主线程任务放在启动子线程之前

(2)实现Runnable接口

  • 定义一个线程任务类实现Runnable接口,重写run()方法
  • 创建任务类对象
  • 把任务类对象交给Thread处理、
  • 调用线程对象的start()方法启动线程

优缺点:

优点:任务类只是实现接口,可以继续继承其他类、实现其他接口,扩展性强。

缺点:需要多一个Runnable对象,如果线程有执行结果是不能直接返回的。

示例代码:

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class Demo1 {
    public static void main(String[] args) {
        //需求:创建两个线程,分别用于打印10个A和10个B,最后观察下输出顺序
        
        //创建任务类对象
        AThread aThread = new AThread();
        BThread bThread = new BThread();

        //把任务类对象交给Thread处理
        Thread t1 = new Thread(aThread);
        Thread t2 = new Thread(bThread);
        
        //调用线程对象的start()方法启动线程
        t1.start();
        t2.start();
    }
}

/**
 * 定义一个线程任务类实现Runnable接口,重写run()方法
 */
class AThread implements Runnable {
    public static final Logger LOGGER = LoggerFactory.getLogger("AThread");
    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            LOGGER.debug("AThread-A{}", i );
        }
    }
}

/**
 * 定义一个线程任务类实现Runnable接口,重写run()方法
 */
class BThread implements Runnable {
    public static final Logger LOGGER = LoggerFactory.getLogger("BThread");
    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            LOGGER.debug("BThread-B{}", i );
        }
    }
}

(3)实现Callable接口

JDK 5.0提供了Callable接口和FutureTask类来实现多线程,这种方式最大的优点:可以返回线程执行完毕后的结果。

1.创建任务对象

  • 定义一个类实现Callable接口,重写call方法,封装要做的事情,和要返回的数据
  • 把Callable类型的对象封装成FutureTask(线程任务对象)

2.把线程任务对象交给Thread对象

3.调用Thread对象的start方法启动线程

4.线程执行完毕后、通过FutureTask对象的的get方法去获取线程任务执行的结果

FutureTask的API

优缺点:

优点:线程任务类只是实现接口,可以继续继承类和实现接口,扩展性强;可以在线程执行完毕后去获取线程执行的结果。

缺点:编码复杂一点。

示例代码:

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

public class Demo1 {

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        //需求:启动两个子线程,分别计算100之内的奇数的和和偶数的和,然后在主线程中再做个汇总,得到总和

        AThread aThread = new AThread();
        BThread bThread = new BThread();

        // 把Callable类型的对象封装成FutureTask(线程任务对象)
        FutureTask<Integer> aFutureTask = new FutureTask<>(aThread);
        FutureTask<Integer> bFutureTask = new FutureTask<>(bThread);

        //把线程任务对象交给Thread对象。
        Thread t1 = new Thread(aFutureTask);
        Thread t2 = new Thread(bFutureTask);

        //调用Thread对象的start方法启动线程
        t1.start();
        t2.start();

        //线程执行完毕后、通过FutureTask对象的的get方法去获取线程任务执行的结果
        Integer aSum = aFutureTask.get();
        Integer bSum = bFutureTask.get();
        int sum =aSum + bSum;
        System.out.println("sum=" +sum);

    }
}

/**
 * 定义一个类实现Callable接口,重写call方法,封装要做的事情,和要返回的数据
 */
class AThread implements Callable<Integer> {
    public static final Logger LOGGER = LoggerFactory.getLogger("AThread");

    @Override
    public Integer call() throws Exception {
        int sum = 0;
        for (int i = 1; i <= 100; i+=2) {
            sum += i;

        }
        return sum;
    }
}
/**
 * 定义一个类实现Callable接口,重写call方法,封装要做的事情,和要返回的数据
 */
class BThread implements Callable<Integer> {
    public static final Logger LOGGER = LoggerFactory.getLogger("BThread");
    @Override
    public Integer call() throws Exception {
        int sum = 0;
        for (int i = 0; i <= 100; i+=2) {
            sum += i;

        }
        return sum;
    }
}

3、Thread类的方法

获取线程名称、设置线程名称、拿到当前线程对象、线程休眠、线程优先执行(join)等方法

示例代码:

public class Demo1 {
    public static void main(String[] args) throws InterruptedException {
        //在主线程序中创建A、B两个子线程
        A a = new A();
        B b = new B();

        //在主线程序中开启A、B两个子线程
        a.start();
        //B线程要等A线程打印完毕,再开始打印
        a.join();

        b.start();
        
    }
}

/**
 * 创建A、B两个线程类,分别打印1~5
 */
class A extends Thread {
    @Override
    public void run() {
        for (int i = 1; i <= 5 ; i++) {
            System.out.println("A-->" +i);
            try {
                //让A线程每打印一次,都要暂停3秒钟
                Thread.sleep(3000);
            }catch (Exception e) {
                e.printStackTrace();
            }

        }
    }
}

class B extends Thread{
    @Override
    public void run(){
        for(int i=1;i<=5;i++){
            System.out.println("B-->"+i);
        }
    }
}

标签:Java,String,配置文件,Thread,线程,new,日志,多线程,public
From: https://blog.csdn.net/weixin_69134024/article/details/142032664

相关文章

  • 【Java】已解决:com.alibaba.com.caucho.hessian.io.HessianProtocolException异常
    文章目录一、分析问题背景二、可能出错的原因三、错误代码示例四、正确代码示例服务端代码客户端代码五、注意事项已解决:com.alibaba.com.caucho.hessian.io.HessianProtocolException异常一、分析问题背景在使用Hessian进行远程调用时,开发者有时会遇到com.al......
  • 【Java】已解决:org.springframework.web.multipart.MultipartException
    文章目录一、分析问题背景二、可能出错的原因三、错误代码示例四、正确代码示例1.配置文件上传限制2.控制器代码五、注意事项已解决:org.springframework.web.multipart.MultipartException一、分析问题背景在使用Spring框架进行文件上传时,开发者可能会遇到o......
  • 【Java】已解决:java.io.IOException
    文章目录一、分析问题背景场景示例:二、可能出错的原因三、错误代码示例错误分析:四、正确代码示例代码改进说明:五、注意事项在Java开发过程中,java.io.IOException是一种常见的异常类型,通常与I/O(输入/输出)操作有关。本文将详细解析该异常的背景、可能的出错原因,提......
  • java面试(9.8)接口和抽象类的区别
    接口:        定义了一组方法规范,但不提供这些方法的具体实现。接口的作用:定义规范:接口主要用于定义一个规范,规定了实现该接口的类必须遵守的规则。实现多继承:一个类可以实现多个接口,从而继承多个接口中定义的方法。解耦合:接口提供了一种解耦合的方式,使得代码......
  • 1-7java_switch_case语句
    Javaswitchcase语句switchcase语句判断一个变量与一系列值中某个值是否相等,每个值称为一个分支。语法switchcase语句语法格式如下:`switch``(expression){````case``value:````//语句````break``;``//可选````case``value:````//语句````break......
  • Javaweb-事务
    注意在当前窗口是修改了的:而在其他窗口是不修改的:select@@autocommit;修改为手动提交:......
  • Javaweb-多表查询案例
    数据准备DROPTABLEIFEXISTSemp;DROPTABLEIFEXISTSdept;DROPTABLEIFEXISTSjob;DROPTABLEIFEXISTSsalarygrade;--部门表CREATETABLEdept(idINTPRIMARYKEYPRIMARYKEY,--部门iddnameVARCHAR(50),--部门名称locVARCHAR(50)--部门所在地);-......
  • Java 后端接口入参 - 联合前端VUE 使用AES完成入参出参加密&解密
    加密效果:解密后的数据就是正常数据:后端:使用的是spring-cloud框架,在gateway模块进行操作<dependency><groupId>com.google.guava</groupId><artifactId>guava</artifactId><version>30.0-jre</version>......
  • Java魔板游戏软件(含代码)
    ✅作者简介:2022年博客新星第八。热爱国学的Java后端开发者,修心和技术同步精进。......
  • JavaWeb学习笔记,关于HTML的入门标签及属性
    一.HTML入门结构标签以及特点   以上标签即为HTML的入门标签,包括了HTML的基本框架结构标签以及部分常用标签,需要注意的是,HTML的语法松散,但我们更要严格要求自己,使用正常符合要求的代码格式,以免后期出现错误而无法及时发现问题,值得提起的还有,<h1>到<h6>是HTML中预定义好......