每日筑基之配置文件&日志&多线程

一.配置文件

1.定义:

在企业,我们常把一些需要灵活配置的数据放在一些文本中,而不是在代码中写死,把这些存储配置信息的文件叫做配置文件.

2.Properties

它是一个map集合,核心作用:Properties是用来代表属性文件的,通过Properties可以读写属性文件里的内容.

(1).常用方法和构造器



import java.io.*;
import java.util.Properties;

/*
properties配置文件
特点:
    1、都只能是键值对
    2、键不能重复
    3、文件后缀一般是.properties结尾的

Properties
    这是一个Map集合(键值对集合),但是我们一般不会当集合使用
    主要用来代表属性文件,通过Properties可以读写属性文件里的内容

读取
    public Properties()  创建Properties集合对象

    public void load(InputStream is/Reader reader)  通过输入流读取文件中的键值对数据
    public String getProperty(String key) 	根据键获取值(其实就是get方法的效果)
    public Set<String> stringPropertyNames()	获取全部键的集合(其实就是ketSet方法的效果)

写出
    public Properties()  创建Properties集合对象

    public Object setProperty(String key, String value) 	保存键值对数据到Properties对象中去。
    public void store(OutputStream os/Writer writer, String comments)	把键值对数据,通过输出流写出到属性文件里去
*/
public class Demo1 {
    public static void main(String[] args) throws Exception {
        //1. 创建一个配置文件对象
        Properties properties = new Properties();

        //2. 读取
        properties.load(new FileReader("F:\\study\\code\\day-10\\user.porperties"));
        String pwd = properties.getProperty("admin");
        //3. 写出
        System.out.println("admin");
        System.out.println(pwd);


        Properties properties1 = new Properties();
        properties1.setProperty("阿吉 ", "123456");
         properties1.store(new FileWriter("F:\\study\\code\\day-10\\user.porperties"),"张家齐二货");
    }
}

2.XML

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

<?xml version="1.0" encoding="UTF-8" ?>
<!--这是注释,以下是XML文件的内容,都是开始标签,结尾标签的形式-->
<!--这是注释XML文件的后缀一般是.xml-->
       <!-- /*
        XML
        全称 Extensible Markup Language, 可扩展标记语言
        本质是一种数据的格式,可以用来存储复杂的数据结构,和数据关系。

        特点
        XML中的“<标签名>” 称为一个标签或一个元素,一般是成对出现的。
    XML中的标签名可以自己定义(可扩展),但必须要正确的嵌套。
    XML中只能有一个根标签。
    XML中的标签可以有属性。
    如果一个文件中放置的是XML格式的数据,这个文件就是XML文件,后缀一般要写成.xml。

    语法
    XML文件的后缀名为:xml,文档声明必须是第一行
    XML中可以定义注释信息:<!–- 注释内容 &ndash;&gt;,快捷键是Ctrl+shift+/
    XML中书写”<”、“&”等,可能会出现冲突,导致报错,此时可以用如下特殊字符替代。
    XML中可以写一个叫CDATA的数据区: <![CDATA[   …内容…  ]]>,里面的内容可以随便写。

    XML的作用和应用场景
    经常用来做为系统的配置文件
    或者作为一种特殊的数据结构,在网络中进行传输。
    */-->
<users>
    <user id="1">
        <name>张无忌</name>
    </user>
    <user id="2">
        <name>赵敏</name>
    </user>
</users>

(1)引用场景

经常用来做为系统的配置文件;或者作为一种特殊的数据结构,在网络中进行传输。

(2)解析XML----框架Dom4j

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

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

/*
需求: 解析b-2.xml,将内容封装到一个List<User对象的集合>

XML解析
    DOM解析思想
        DOM (document Object Model)文档对象模型
        将文档的各个组成部分看做是对应的对象
        首先会将xml文件全部加载到内存,在内存中形成一个树状结构,在获取对应的值
        DOM解析思想就是一层一层的进入,一层一层的解析

    对象分类
        Document:整个xml文档对象
        Element: 标签对象
        Attribute:属性对象
        Text标签体:文本对象

    DOM4J解析XML准备工作
        1、将dom4j的jar包加入到项目中
        2、创建DOM4]解析器对象SAXReader,获取Document文档对象,获取根标签对象
        3、从根标签对象开始往下层层解析


    详细API
        SAXReader:Dom4j提供的解析器,可以认为是代表整个Dom4j框架
            public SAXReader() 	构建Dom4J的解析器对象
            public Document read(String path)	把XML文件读成Document对象
        Element getRootElement() 	获得根元素对象
            public String getName()	得到元素名字
            public List<Element> elements()	得到当前元素下所有子元素
            public List<Element> elements(String name)	得到当前元素下指定名字的子元素返回集合
            public Element element(String name)	得到当前元素下指定名字的子元素,如果有很多名字相同的返回第一个
            public String  attributeValue(String name)	通过属性名直接得到属性值
            public String elementText(子元素名)	得到指定名称的子元素的文本
            public String getText()	得到文本

 */
public class Demo2 {
    public static void main(String[] args) throws Exception {
        ArrayList<User> users = new ArrayList<>();
        //构建saxreader解析器对象
        SAXReader reader = new SAXReader();
        //将文件读成Document对象
        Document document = reader.read(new FileReader("F:\\study\\code\\day-10\\b-2.xml"));
        //得到根标签元素对象
        Element rootElement = document.getRootElement();
        //得到根标签的名字
        String rootname = rootElement.getName();
        System.out.println("rootname="+rootname);
        //将根标签下的所有子标签放入集合返回
        List<Element> elements = rootElement.elements();
        System.out.println(elements.size());//2
        //遍历子标签的集合,得到想要的元素
        for (Element element : elements) {
            System.out.println("=======");
            String name = element.getName();
            String id = element.attributeValue("id");
            System.out.println("子标签名字"+name+"-"+id);

            List<Element> elements1 = element.elements();
            System.out.println(elements1.size());//elements1子标签下几个子标签 4
            String username = element.element("name").getText();//先得到名字整个标签,再只拿文本
            System.out.println("name"+username);
            String password = element.element("password").getText();//先得到名字整个标签,再只拿文本
            System.out.println("password"+password);
            String address = element.element("address").getText();//先得到名字整个标签,再只拿文本
            System.out.println("address"+address);
            String gender = element.element("gender").getText();//先得到名字整个标签,再只拿文本
            System.out.println("gender"+gender);
            System.out.println("=======");
            User user = new User(username,password,address,gender);
            users.add(user);
            for (User u : users) {
                System.out.println(u);
            }

        }
    }
}
class User{
    private String name;
    private String password;
    private String adress;
    private String gender;

    public User() {
    }

    public User(String name, String password, String adress, String gender) {
        this.name = name;
        this.password = password;
        this.adress = adress;
        this.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 getAdress() {
        return adress;
    }

    public void setAdress(String adress) {
        this.adress = adress;
    }

    public String getGender() {
        return gender;
    }

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

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


(3)方法

3.日志

记录程序运行的点点滴滴

(1)日志技术

可以将系统执行的信息,方便的记录到指定的位置(控制台、文件中、数据库中)。

可以随时以开关的形式控制日志的启停,无需侵入到源代码中去进行修改。

(2)体系结构

(3)Logback日志框架

(4)Logbacku快速入门

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

/*
需求
    使用Logback日志框架,纪录系统的运行信息。
实现步骤
    1. 导入Logback框架到项目中去。
    2. 将Logback框架的核心配置文件logback.xml直接拷贝到src目录下(必须是src下)。
    4. 创建Logback框架提供的Logger对象,然后用Logger对象调用其提供的方法就可以记录系统的日志信息。
        public static final Logger LOGGER = LoggerFactory.getLogger("当前类类名");
    5. 打印日志
        LOGGER.info("日志信息")
        LOGGER.debug("日志信息")
        LOGGER.error("日志信息")
*/
public class Demo1 {
    public static final  Logger LOGGER = LoggerFactory.getLogger("Demo1");

    public static void main(String[] args) {
      /*  LOGGER.info();//输出重要东西
        LOGGER.debug();//测试
        LOGGER.warn();//
        LOGGER.error();//输出错误*/
        LOGGER.info("开始执行div方法");
        LOGGER.warn("b不能是0");
        div(2,1);
        div(2,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);
            throw new RuntimeException(e);
        }
    }
}

(5)日志级别

(6)为什么要学习日志级别

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

二.多线程

1.定义

简单来说就是电脑在做一件事,单线程,在做一件事;多线程,在做多件事

2.多线程的创建方式

(1)继承Thread类

定义一个子类继承线程类java.lang.Thread,重写run()方法

创建子类的对象

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

import org.dom4j.io.SAXReader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/*
多线程
    让程序同时做多件事

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

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

注意事项
    1、启动线程必须是调用start方法,不是调用run方法。
    2、直接调用run方法会当成普通方法执行,只有调用start方法才是启动一个新的线程执行。
    3、不要将主线任务放在start方法之前,这样主线程一直是先跑完的,相当于是一个单线程的效果了。

扩展
    对于单核cpu来讲, 多线程是一种假象
*/
public class Demo1 {
    public static final Logger LOGGER=LoggerFactory.getLogger("Demo1");
    public static void main(String[] args) {
        //需求:创建两个线程,分别用于打印10个A和10个B,最后观察下输出顺序
        LOGGER.debug("开始");
        Athraed athraed = new Athraed();
        Bthread bthread = new Bthread();
        athraed.start();
        bthread.start();
    }
}
class Athraed extends Thread{
    public static final Logger LOGGER=LoggerFactory.getLogger("Athraed");
    @Override
    public void run() {
        for(int i=0;i<10;i++){
            LOGGER.debug("A-"+i);
        }
    }
}
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("B-"+i);
        }
    }
}
1.优缺点

优点:编码简单

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

(3)实现Runnable接口

定义一个线程任务类实现Runnable接口,重写run()方法

创建任务类对象

把任务类对象交给Thread处理

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

/*
多线程的创建方式二:实现Runnable接口
    1. 定义一个线程任务类实现Runnable接口,重写run()方法
    2. 创建任务类对象
    3. 把任务类对象交给Thread处理
        public Thread(Runnable target)
    4. 调用线程对象的start()方法启动线程

优缺点
    优点:任务类只是实现接口,可以继续继承其他类、实现其他接口,扩展性强。
    缺点:需要多一个Runnable对象。
*/
public class Demo1 {
    public static final Logger LOGGER= LoggerFactory.getLogger("Demo1");
    public static void main(String[] args) {
        LOGGER.info("奥利给,干了兄弟们");
        //需求:创建两个线程,分别用于打印10个A和10个B,最后观察下输出顺序
        Arunable arunable = new Arunable();
        Brunable brunable = new Brunable();
        //把任务类对象交给Thread处理
        Thread thread1 = new Thread(arunable);
        //设置thread的名字
        thread1.setName("t1-a");
        Thread thread2 = new Thread(brunable);
        thread1.start();
        thread2.start();

    }
}
//任务类
class Arunable implements Runnable{
    public static final Logger LOGGER= LoggerFactory.getLogger("Arunable");
    @Override
    public void run() {
        //获取当前线程
        System.out.println("执行run当前线程的名字"+Thread.currentThread());
        for (int i=0;i<10;i++){
            LOGGER.debug("A-"+i);
    }
    }
}
class Brunable implements Runnable{
    public static final Logger LOGGER= LoggerFactory.getLogger("Brunable");
    @Override
    public void run() {
        System.out.println("执行run当前线程的名字"+Thread.currentThread());
        for (int i=0;i<10;i++){
            LOGGER.debug("B-"+i);
        }
    }
}
1.优缺点

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

缺点:需要多一个Runnable对象。

(3)实现Callable接口

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

把线程任务对象交给Thread对象。 调用Thread对象的start方法启动线程。

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


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

/*
多线程的创建方式三:实现Callable接口
    1. 创建任务对象
        定义一个类实现Callable接口,重写call方法,封装要做的事情,和要返回的数据
        把Callable类型的对象封装成FutureTask(线程任务对象)
            public FutureTask<>(Callable call)	把Callable对象封装成FutureTask对象
            public V get() throws Exception	获取线程执行call方法返回的结果
    2. 把线程任务对象交给Thread对象。
    3. 调用Thread对象的start方法启动线程。
    4. 线程执行完毕后、通过FutureTask对象的的get方法去获取线程任务执行的结果

优缺点
    优点:线程任务类只是实现接口,可以继续继承类和实现接口,扩展性强;可以在线程执行完毕后去获取线程执行的结果
    缺点:编码复杂一点。
*/
public class Demo1 {

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        //需求:启动两个子线程,分别计算100之内的奇数的和和偶数的和,然后在主线程中再做个汇总,得到总和
        Athead athead = new Athead();
        Bthead bthead = new Bthead();
        FutureTask<Integer> aFuturetask = new FutureTask<Integer>(athead);
        FutureTask<Integer> bFuturetask = new FutureTask<Integer>(bthead);
        Thread  t1= new Thread(aFuturetask);
        Thread  t2= new Thread(bFuturetask);
        t1.start();
        t2.start();
        Integer asum = aFuturetask.get();
        Integer bsum = bFuturetask.get();
        int sum=asum+bsum;
        System.out.println(sum);
    }
}
class Athead implements Callable<Integer> {

    @Override
    public Integer call() throws Exception {
        int sum=0;
        for(int i=1;i<=100;i+=2){
            sum+=i;
        }
        return sum;
    }
}
class Bthead implements Callable<Integer>{

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

1.优缺点

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

缺点:编码复杂一点。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值