增强day11-特殊文件、日志技术、多线程

  1. 特殊文件
    1. Properties属性文件
      1. 可以很方便的存储一些类似于键值对的数据。经常当做软件的配置文件使用。
      2. 属性文件里面的每一行都是一个键值对,键和值中间用=隔开。比如: admin=123456
      3. #表示这样是注释信息,是用来解释这一行配置是什么意思
      4. 每一行末尾不要习惯性加分号,以及空格等字符;不然会把分号,空格会当做值的一部分。
      5. 键不能重复,值可以重复、
      6. 可以使用Properties读取属性文件中的键值对
        1. Properties是Map接口下面的一个实现类,所以Properties也是一种双列集合,用来存储键值对。 但是一般不会把它当做集合来使用。
        2. Properties类的对象,用来表示属性文件,可以用来读取属性文件中的键值对。
/**
 * 目标:掌握使用Properties类读取属性文件中的键值对信息。
 */
public class PropertiesTest1 {
    public static void main(String[] args) throws Exception {
        // 1、创建一个Properties的对象出来(键值对集合,空容器)
        Properties properties = new Properties();
        System.out.println(properties);

        // 2、开始加载属性文件中的键值对数据到properties对象中去
        properties.load(new FileReader("properties-xml-log-app\\src\\users.properties"));
        System.out.println(properties);

        // 3、根据键取值
        System.out.println(properties.getProperty("赵敏"));
        System.out.println(properties.getProperty("张无忌"));

        // 4、遍历全部的键和值。
        //获取键的集合
        Set<String> keys = properties.stringPropertyNames();
        for (String key : keys) {
            //再根据键获取值
            String value = properties.getProperty(key);
            System.out.println(key + "---->" + value);
        }
		
        properties.forEach((k, v) -> {
            System.out.println(k + "---->" + v);
        });
    }
}


public class PropertiesTest2 {
    public static void main(String[] args) throws Exception {
        // 1、创建Properties对象出来,先用它存储一些键值对数据
        Properties properties = new Properties();
        properties.setProperty("张无忌", "minmin");
        properties.setProperty("殷素素", "cuishan");
        properties.setProperty("张翠山", "susu");

        // 2、把properties对象中的键值对数据存入到属性文件中去
        properties.store(new FileWriter("properties-xml-log-app/src/users2.properties")
                         , "i saved many users!");

    }
}
  1. XML文件
    1. 能够表示更加复杂的数据关系,比如要表示多个用户的用户名、密码、家乡、性别等。在后面,也经常当做软件的配置文件使用。
<?xml version="1.0" encoding="UTF-8" ?>
<!-- 注释:以上抬头声明必须放在第一行,必须有 -->
<!--  根标签只能有一个 -->
<users>
    <user id="1" desc="第一个用户">
        <name>张无忌</name>
        <sex></sex>
        <地址>光明顶</地址>
        <password>minmin</password>
    </user>
    <people>很多人</people>
    <user id="2">
        <name>敏敏</name>
        <sex></sex>
        <地址>光明顶</地址>
        <password>wuji</password>
    </user>
</users>
  2. XML解析:Dom4J
public class Dom4JTest1 {
    public static void main(String[] args) throws Exception {
        // 1、创建一个Dom4J框架提供的解析器对象
        SAXReader saxReader = new SAXReader();

        // 2、使用saxReader对象把需要解析的XML文件读成一个Document对象。
        Document document =
                saxReader.read("properties-xml-log-app\\src\\helloworld.xml");

        // 3、从文档对象中解析XML文件的全部数据了
        Element root = document.getRootElement();
        System.out.println(root.getName());

        // 4、获取根元素下的全部一级子元素。
        // List<Element> elements = root.elements();
        List<Element> elements = root.elements("user");
        for (Element element : elements) {
            System.out.println(element.getName());
        }

        // 5、获取当前元素下的某个子元素。
        Element people = root.element("people");
        System.out.println(people.getText());

        // 如果下面有很多子元素user,默认获取第一个。
        Element user = root.element("user");
        System.out.println(user.elementText("name"));

        // 6、获取元素的属性信息呢?
        System.out.println(user.attributeValue("id"));
        Attribute id = user.attribute("id");
        System.out.println(id.getName());
        System.out.println(id.getValue());

        List<Attribute> attributes = user.attributes();
        for (Attribute attribute : attributes) {
            System.out.println(attribute.getName() + "=" + attribute.getValue());
        }

        // 7、如何获取全部的文本内容:获取当前元素下的子元素文本值
        System.out.println(user.elementText("name"));
        System.out.println(user.elementText("地址"));
        System.out.println(user.elementTextTrim("地址")); // 取出文本去除前后空格
        System.out.println(user.elementText("password"));

        Element data = user.element("data");
        System.out.println(data.getText());
        System.out.println(data.getTextTrim()); // 取出文本去除前后空格
    }
}
  3. XML写入
public class Dom4JTest2 {
    public static void main(String[] args) {
        // 1、使用一个StringBuilder对象来拼接XML格式的数据。
        StringBuilder sb = new StringBuilder();
        sb.append("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\r\n");
        sb.append("<book>\r\n");
        sb.append("\t<name>").append("从入门到跑路").append("</name>\r\n");
        sb.append("\t<author>").append("dlei").append("</author>\r\n");
        sb.append("\t<price>").append(999.99).append("</price>\r\n");
        sb.append("</book>");

        try (
                BufferedWriter bw = new BufferedWriter(new FileWriter("properties-xml-log-app/src/book.xml"));
                ){
            bw.write(sb.toString());
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
}
  1. 日志
    1. 记录了程序运行过程中产生的各种数据。
    2. 日志框架:Logback
    3. image.png
public class LogBackTest {
    // 创建一个Logger日志对象
    public static final Logger LOGGER = LoggerFactory.getLogger("LogBackTest");

    public static void main(String[] args) {
        //while (true) {
            try {
                LOGGER.info("chu法方法开始执行~~~");
                chu(10, 0);
                LOGGER.info("chu法方法执行成功~~~");
            } catch (Exception e) {
                LOGGER.error("chu法方法执行失败了,出现了bug~~~");
            }
        //}
    }

    public static void chu(int a, int b){
        LOGGER.debug("参数a:" + a);
        LOGGER.debug("参数b:" + b);
        int c = a / b;
        LOGGER.info("结果是:" + c);
    }
}
  1. 日志级别
  2. Logback只输出大于或者等于核心配置文件配置的日志级别信息。小于配置级别的日志信息,不被记录。
    1. 配置的是trace,则trace、debug、info、warn、error级别的日志都被输出
    2. 配置的是debug, 则debug、info、warn、error级别的日志被输出
    3. 配置的是info,则info、warn、error级别的日志被输出
  3. 多线程
  • 创建线程1:继承Thread
1.定义一个子类继承Thread类,并重写run方法
2.创建Thread的子类对象
3.调用start方法启动线程(启动线程后,会自动执行run方法中的代码)

public class MyThread extends Thread{
    // 2、必须重写Thread类的run方法
    @Override
    public void run() {
        // 描述线程的执行任务。
        for (int i = 1; i <= 5; i++) {
            System.out.println("子线程MyThread输出:" + i);
        }
    }
}

public class ThreadTest1 {
    // main方法是由一条默认的主线程负责执行。
    public static void main(String[] args) {
        // 3、创建MyThread线程类的对象代表一个线程
        Thread t = new MyThread();
        // 4、启动线程(自动执行run方法的)
        t.start(); 

        for (int i = 1; i <= 5; i++) {
            System.out.println("主线程main输出:" + i);
        }
    }
}
  • 创建线程2:实现Runnable接口
1.先写一个Runnable接口的实现类,重写run方法(这里面就是线程要执行的代码)
2.再创建一个Runnable实现类的对象
3.创建一个Thread对象,把Runnable实现类的对象传递给Thread
4.调用Thread对象的start()方法启动线程(启动后会自动执行Runnable里面的run方法)


/**
 * 1、定义一个任务类,实现Runnable接口
 */
public class MyRunnable implements Runnable{
    // 2、重写runnable的run方法
    @Override
    public void run() {
        // 线程要执行的任务。
        for (int i = 1; i <= 5; i++) {
            System.out.println("子线程输出 ===》" + i);
        }
    }
}


public class ThreadTest2 {
    public static void main(String[] args) {
        // 3、创建任务对象。
        Runnable target = new MyRunnable();
        // 4、把任务对象交给一个线程对象处理。
        //  public Thread(Runnable target)
        new Thread(target).start();

        for (int i = 1; i <= 5; i++) {
            System.out.println("主线程main输出 ===》" + i);
        }
    }
}
  • 创建线程3:直接创建Runnable接口的匿名内部类对象
public class ThreadTest2_2 {
    public static void main(String[] args) {
        // 1、直接创建Runnable接口的匿名内部类形式(任务对象)
        Runnable target = new Runnable() {
            @Override
            public void run() {
                for (int i = 1; i <= 5; i++) {
                    System.out.println("子线程1输出:" + i);
                }
            }
        };
        new Thread(target).start();

        // 简化形式1:
        new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 1; i <= 5; i++) {
                    System.out.println("子线程2输出:" + i);
                }
            }
        }).start();

        // 简化形式2:
        new Thread(() -> {
                for (int i = 1; i <= 5; i++) {
                    System.out.println("子线程3输出:" + i);
                }
        }).start();

        for (int i = 1; i <= 5; i++) {
            System.out.println("主线程main输出:" + i);
        }
    }
}
  • 创建线程4:

1.先定义一个Callable接口的实现类,重写call方法
2.创建Callable实现类的对象
3.创建FutureTask类的对象,将Callable对象传递给FutureTask
4.创建Thread对象,将Future对象传递给Thread
5.调用Thread的start()方法启动线程(启动后会自动执行call方法)
等call()方法执行完之后,会自动将返回值结果封装到FutrueTask对象中
6.调用FutrueTask对的get()方法获取返回结果

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

// Step 1: 实现 Callable 接口
class MyCallable implements Callable<Integer> {
    @Override
    public Integer call() throws Exception {
        int result = 0;
        for (int i = 1; i <= 10; i++) {
            result += i;
        }
        return result;
    }
}

public class Main {
    public static void main(String[] args) {
        // Step 2: 创建 Callable 实现类的对象
        Callable<Integer> callable = new MyCallable();

        // Step 3: 创建 FutureTask 对象,将 Callable 对象传递给 FutureTask
        FutureTask<Integer> futureTask = new FutureTask<>(callable);

        // Step 4: 创建 Thread 对象,将 Future 对象传递给 Thread
        Thread thread = new Thread(futureTask);

        // Step 5: 调用 Thread 的 start() 方法启动线程
        thread.start();

        // Step 6: 调用 FutureTask 的 get() 方法获取返回结果
        try {
            Integer result = futureTask.get(); // 这里会阻塞,直到线程执行完毕并返回结果
            System.out.println("线程执行结果:" + result);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值