每日分享之-配置文件&日志&多线程

1.配置文件

1.1配置文件的介绍

在企业开发过程中,我们习惯把一些需要灵活配置的数据放在一些文本文件中,而不是在Java代码

写死 我们把这种存放程序配置信息的文件,统称为配置文件

配置文件一般要求有明确的格式,以方便读写操作。

1.2Properties

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

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

Properties的常用方法:

Properties的读取和写入方法:

读取:

写入:

1.3XML

XML全称Extensible Markup Language, 是可扩展标记语言,本质是一种数据的格式,可以用来存储复杂的数据结构,和数据关系。

XML的特点:

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

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

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

4.XML文件中可以定义注释信息:<!–- 注释内容 -->

5.标签必须成对出现,有开始,有结束标签: <name></name>

详细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() 得到文本

实例:使用dom4j将xml文件中的内容封装到一个List<User对象的集合>

public class Demo2 {
    public static void main(String[] args) throws Exception {

        //需求: 解析b-2.xml,将内容封装到一个List<User对象的集合>
        //将dom4j的jar包加入到项目中
        //创建DOM4]解析器对象SAXReader,获取Document文档对象,获取根标签对象
        SAXReader saxReader = new SAXReader();
        Document document = saxReader.read(new FileReader("F:\\WorkSpace\\JaveSePlus\\day010-review\\src\\b-2.xml"));
        //获得根元素对象,开始往下层层解析
        Element root = document.getRootElement();
        //获取根标签的名字
        String rootName = root.getName();
        System.out.println("rootName:" + rootName);
        //获取根标签下所有子标签
        List<Element> elements = root.elements();
        ArrayList<User> users = new ArrayList<User>();
        //遍历标签的集合
        for (Element element : elements) {
            System.out.println("========");
            //获取子标签的名字
            String name = element.getName();
            //获取子标签的id属性值
            String id = element.attributeValue("id");
            System.out.println("子标签名字:" + name + id);
            //获取子标签的name标签的文本
            String userName = element.element("name").getText();
            //获取子标签的password标签的文本
            String password = element.element("password").getText();
            //获取子标签的address标签的文本
            String address = element.element("address").getText();
            //获取子标签的gender标签的文本
            String gender = element.element("gender").getText();
            users.add(new User(userName, password, address, gender));
        }
            users.forEach(System.out::println);

    }
}

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

    public User() {
    }

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

    /**
     * 获取
     * @return name
     */
    public String getName() {
        return name;
    }

    /**
     * 设置
     * @param name
     */
    public void setName(String name) {
        this.name = name;
    }

    /**
     * 获取
     * @return password
     */
    public String getPassword() {
        return password;
    }

    /**
     * 设置
     * @param password
     */
    public void setPassword(String password) {
        this.password = password;
    }

    /**
     * 获取
     * @return address
     */
    public String getAddress() {
        return address;
    }

    /**
     * 设置
     * @param address
     */
    public void setAddress(String address) {
        this.address = address;
    }

    /**
     * 获取
     * @return gender
     */
    public String getGender() {
        return gender;
    }

    /**
     * 设置
     * @param gender
     */
    public void setGender(String gender) {
        this.gender = gender;
    }

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

2.日志技术

日志:好比生活中的日记,可以记录你生活中的点点滴滴。 程序中的日志,通常就是一个文件,里面记录的是程序运行过程中的各种信息。

日志的优点:可以将系统执行的信息,方便的记录到指定的位置(控制台、文件中、数据库中)。 可以随时以开关的形式控制日志的启停,无需侵入到源代码中去进行修改。

2.1Logback快速入门

需求
    使用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("日志信息")

2.2Logback设置日志级别

日志的级别:常用的有info、warn、error

在logback.xml中可以自己设置日志的级别,当级别大于所设置的级别时,日志才会输出

3.多线程

线程:简单的说,就是计算机在做一件事

单线程:在计算机中同一时间只能做一件事

多线程:在计算机中同一时间可以做多件事

其实多线程在我们的生活中的使用场景很多,比如网盘的上传下载,12306的多窗口售票等等

它的主要好处有:1. 减少队列阻塞带来的影响   2. 提高CPU的利用率

3.1线程的创建方式

线程的创建方式有三种:

多线程的创建方式一:继承Thread类
    1. 定义一个子类继承线程类java.lang.Thread,重写run()方法
    2. 创建子类的对象
    3. 调用子类对象的start()方法启动线程(底层会自动去执行run方法)
优缺点
    优点:编码简单
    缺点:线程类已经继承Thread,无法继承其他类,不利于功能的扩展。
注意事项
    1、启动线程必须是调用start方法,不是调用run方法。
    2、直接调用run方法会当成普通方法执行,只有调用start方法才是启动一个新的线程执行。
    3、不要将主线任务放在start方法之前,这样主线程一直是先跑完的,相当于是一个单线程的效果了。

实例:创建两个线程,分别打印10个A和10个B,观察输出顺序

public class Demo1 {
    public static void main(String[] args) {
        //2. 创建子类的对象
        ThreadA threadA = new ThreadA();
        ThreadB threadB = new ThreadB();
        //3. 调用子类对象的start()方法启动线程(底层会自动去执行run方法)
        threadA.start();
        threadB.start();

    }
}
//创建两个线程,并且继承线程java.lang.Thread,重写run()方法
class ThreadA extends Thread {
    public static final Logger LOGGER = LoggerFactory.getLogger("ThreadA");
    @Override
    public void run() {
        for (int i = 0; i < 10; i++){
            LOGGER.info("A->"+i);
        }
    }
}

class ThreadB extends Thread {
    public static final Logger LOGGER = LoggerFactory.getLogger("ThreadB");
    @Override
    public void run() {
        for (int i = 0; i < 10; i++){
            LOGGER.info("B->"+i);
        }
    }
}

最终打印结果:

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

优缺点
    优点:任务类只是实现接口,可以继续继承其他类、实现其他接口,扩展性强。
    缺点:需要多一个Runnable对象。

实例:创建两个线程,分别打印10个A和10个B,观察输出顺序

public class Demo1 {
    public static void main(String[] args) {
        // 2. 创建任务类对象
        ThreadA threadA = new ThreadA();
        ThreadB threadB = new ThreadB();
        //3. 把任务类对象交给Thread处理
        //public Thread(Runnable target)
        Thread threada = new Thread(threadA);
        Thread threadb = new Thread(threadB);
        //4. 调用线程对象的start()方法启动线程
        threada.start();
        threadb.start();

    }
}

// 1. 定义两个线程任务类实现Runnable接口,重写run()方法
class ThreadA implements Runnable {
    public static final Logger LOGGER = LoggerFactory.getLogger("ThreadA");

    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            LOGGER.info("A->" + i);
        }
    }
}

class ThreadB implements Runnable {
    public static final Logger LOGGER = LoggerFactory.getLogger("ThreadB");

    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            LOGGER.info("B->" + i);
        }
    }
}

最终打印结果:

多线程的创建方式三:实现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方法去获取线程任务执行的结果

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

启动两个子线程,分别计算100之内的奇数的和和偶数的和,然后在主线程中再做个汇总,得到总和:

public class Demo1 {
    public static final Logger LOGGER = LoggerFactory.getLogger("Demo1");
    public static void main(String[] args) throws ExecutionException, InterruptedException {

        //把Callable类型的对象封装成FutureTask(线程任务对象)
        ThreadA threadA = new ThreadA();
        ThreadB threadB = new ThreadB();
        //public FutureTask<>(Callable call)	把Callable对象封装成FutureTask对象
        FutureTask<Integer> ftA = new FutureTask<>(threadA);
        FutureTask<Integer> ftB = new FutureTask<>(threadB);
        //  2. 把线程任务对象交给Thread对象。
        Thread thread1 = new Thread(ftA);
        Thread thread2 = new Thread(ftB);
        thread1.start();
        thread2.start();
        //public V get() throws Exception	获取线程执行call方法返回的结果
        Integer i = ftA.get();
        Integer j = ftB.get();
        //4. 线程执行完毕后、通过FutureTask对象的的get方法去获取线程任务执行的结果
        LOGGER.info("奇数和为{}",i);
        LOGGER.info("偶数和为{}",j);
        LOGGER.info("总和为{}",i+j);
    }
}

// 1. 创建任务对象
// 定义一个类实现Callable接口,重写call方法,封装要做的事情,和要返回的数据
class ThreadA implements Callable<Integer> {
    int count = 0;

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

class ThreadB implements Callable<Integer> {
    int count = 0;

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

3.2Thread类的方法

  • 40
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值