首页 > 其他分享 >day10-配置文件&日志&多线程

day10-配置文件&日志&多线程

时间:2024-09-10 21:51:04浏览次数:13  
标签:String 配置文件 对象 void Thread 线程 day10 多线程 public

一、配置文件

1.1 properties配置文件

properties配置文件
特点:
 1、都只能是键值对
 2、键不能重复
 3、文件后缀一般是.properties结尾的
​
Properties
 这是一个Map集合(键值对集合),但是我们一般不会当集合使用
 主要用来代表属性文件,通过Properties可以读写属性文件里的内容
构造器说明
public Properties()用于构建Properties集合对象(空容器)

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

读取:磁盘---->内存

常用方法说明
public void load(InputStream is)通过字节输入流,读取属性文件里的键值对数据
public void load(Reader reader)通过字符输入流,读取属性文件里的键值对数据
public String getProperty(String key)根据键获取值(其实就是get方法的效果)
public Set<String> stringPropertyNames()获取全部键的集合(其实就是ketSet方法的效果)
public static void main(String[] args) throws IOException {
        //1. 创建一个配置文件对象
        Properties properties = new Properties();
        //2. 读取
        properties.load(new FileInputStream("day10-code\\xml\\user.properties"));
//        String value = properties.getProperty("admin");
//        System.out.println("admin = " + value);
//        String lisi = properties.getProperty("lisi","000000");
//        System.out.println("lisi = " + lisi);
        Set<String> keySet = properties.stringPropertyNames();
        for (String key : keySet) {
            String value = properties.getProperty(key);
            System.out.println(key + " = " + value);
        }
​
}

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

写入:内存---->磁盘

常用方法说明
public Object setProperty(String key, String value)保存键值对数据到Properties对象中去。
public void store(OutputStream os, String comments)把键值对数据,通过字节输出流写出到属性文件里去
public void store(Writer w, String comments)把键值对数据,通过字符输出流写出到属性文件里去
public static void main(String[] args) throws IOException {
        // 写出
        Properties pro2 = new Properties();
        pro2.setProperty("zhu", "猪小贱");
        pro2.setProperty("lin","哼哼猪");
        pro2.setProperty("pang","羊习习");
        pro2.store(new FileOutputStream("day10-code\\xml\\user2.properties"),null);
}

总结

Properties的作用?具体如何使用?

1.可以加载属性文件中的数据到Properties对象中来

void load(Reader reader)

public String getProperty(String key) 根据键获取值

2.可以存储Properties属性集的键值对数据到属性文件中去

void store(Writer writer, String comments) 设置键值

public Object setProperty(String key, String value)

1.2 XML配置文件

XML
 全称 Extensible Markup Language, 可扩展标记语言
 本质是一种数据的格式,可以用来存储复杂的数据结构,和数据关系。
​
特点
 XML中的“<标签名>” 称为一个标签或一个元素,一般是成对出现的。
 XML中的标签名可以自己定义(可扩展),但必须要正确的嵌套。
 XML中只能有一个根标签。
 XML中的标签可以有属性。
 如果一个文件中放置的是XML格式的数据,这个文件就是XML文件,后缀一般要写成.xml。
​
语法
 XML文件的后缀名为:xml,文档声明必须是第一行
 XML中可以定义注释信息:<!–- 注释内容 -->,快捷键是Ctrl+shift+/
 XML中书写”<”、“&”等,可能会出现冲突,导致报错,此时可以用如下特殊字符替代。
 XML中可以写一个叫CDATA的数据区: <![CDATA[   …内容…  ]]>,里面的内容可以随便写。
​
XML的作用和应用场景
    作用:1)作为软件的配置文件   2)用于进行存储数据和传输数据
 经常用来做为系统的配置文件
 或者作为一种特殊的数据结构,在网络中进行传输。

 

 

1.2.1 Dom4j解析XML得到Document对象

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

构造器/方法说明
public SAXReader()构建Dom4J的解析器对象
public Document read(String path)把XML文件读成Document对象

Document

方法名说明
Element getRootElement()获得根元素对象

Element提供的方法

方法名说明
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()得到文本
XML解析案例

需求:

利用Dom4J框架,将contacts.xml文件中的联系人数据,解析出来,封装成List集合,并遍历输出。

 

public class Demo2 {
    public static void main(String[] args) throws FileNotFoundException, DocumentException {
        List<User> userList = new ArrayList();
        //2.创建DOM4]解析器对象SAXReader,获取Document文档对象,获取根标签对象
        SAXReader saxReader = new SAXReader();
        //读取XML文件,读取到内存
        Document document = saxReader.read(new FileReader("day10-code/user.xml"));
        //3.从根标签对象开始往下层层解析
        //3.1 获取根标签的名字
        Element rootElement = document.getRootElement();
        String name = rootElement.getName();
        System.out.println("根标签的名字:" + name);
        //3.2 获取根标签下的所有子标签
        List<Element> elements = rootElement.elements();
        System.out.println("根标签下的所有子标签个数:" + elements.size());
        //3.3 遍历标签的集合
        for (Element element : elements) {
            System.out.println("==========================");
            String id = element.attributeValue("id");
            String elementName = element.getName();
            System.out.println("子标签的名字:" + elementName + "-" + id);
            String userName = element.element("name").getText();
            System.out.println("子标签下的name标签的文本:name=" + userName);
            String userPassword = element.element("password").getText();
            System.out.println("子标签下的password标签的文本:password=" + userPassword);
            String userAddress = element.element("address").getText();
            System.out.println("子标签下的address标签的文本:address=" + userAddress);
            String userGender = element.element("gender").getText();
            System.out.println("子标签下的gender标签的文本:gender=" + userGender);
            //3.4 封装对象到一个List<User对象的集合>
            userList.add(new User(userName, userGender, userAddress, userPassword));
        }
        System.out.println("==========================");
        System.out.println(userList);
​
​
​
    }
}
class User{
    private String name;
    private String gender;
    private String address;
    private String password;
​
    public User() {
    }
​
    public User(String name, String gender, String address, String password) {
        this.name = name;
        this.gender = gender;
        this.address = address;
        this.password = password;
    }
​
    public String getName() {
        return name;
    }
​
    public void setName(String name) {
        this.name = name;
    }
​
    public String getGender() {
        return gender;
    }
​
    public void setGender(String gender) {
        this.gender = gender;
    }
​
    public String getAddress() {
        return address;
    }
​
    public void setAddress(String address) {
        this.address = address;
    }
​
    public String getPassword() {
        return password;
    }
​
    public void setPassword(String password) {
        this.password = password;
    }
​
    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", gender='" + gender + '\'' +
                ", address='" + address + '\'' +
                ", password='" + password + '\'' +
                '}';
    }
}

二、日志

1、什么是日志?

用来记录程序运行过程中的信息,并可以进行永久存储。

2、常见的日志实现框架有哪些?

Log4J、Logback(我们重点学习的,其他的都大同小异)

Logback是基于slf4j日志接口实现的日志框架

3、使用Logback至少需要使用哪几个模块?

slf4j-api:日志接口

logback-core:基础模块

logback-classic:功能模块,它完整实现了slf4j API

2.1 Logback

需求
    使用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("日志信息")//try-catch中给错误信息打日志
public class Demo1 {
    public static final Logger LOGGER = LoggerFactory.getLogger("Demo1");
​
    public static void main(String[] args) {
        LOGGER.info("开始执行div方法");
        div(2,2);
        div(2,0);
    }
    public static int div(int a,int b){
        LOGGER.debug("方法执行了,a="+ a + ",b="+b);
        LOGGER.debug("方法执行了,a={},b={}",a,b);
        LOGGER.warn("除数不能为0");
        try {
            int c = a/b;
            return c;
        }catch (Exception e){
            LOGGER.error("方法执行出错了,出错信息是{}/{}",a,b);
            e.printStackTrace();
            throw new RuntimeException("出错了");
        }
​
    }
}

 

2.2 日志级别

1、设置日志输出级别的作用是什么?

用于控制系统中哪些日志级别是可以输出的

2、Logback的日志级别是什么样的?

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

级别程度依次是:TRACE< DEBUG< INFO<WARN<ERROR

默认级别是debug(忽略大小写),只输出当前级别及高于该级别的日志

三、多线程

线程
    简单的说,就是计算机在做一件事
​
单线程
    在计算机中同一时间只能做一件事
​
多线程
    在计算机中同一时间可以做多件事
    它的主要好处有:1. 减少队列阻塞带来的影响   2. 提高CPU的利用率

3.1 多线程的创建方式一:继承Thread类

线程的创建方式一:继承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,最后观察下输出顺序
        // 2. 创建子类的对象
        AThread aThread = new AThread();
        BThread bThread = new BThread();
        // 3. 调用子类对象的start()方法启动线程(底层会自动去执行run方法)
        LOGGER.info("开始执行");
        aThread.start();
        bThread.start();
        // 4. 将耗时多的主线程放在子线程后再执行(主线程和主线程会一起交替运行)
        for (int i = 0; i < 100; i++) {
            System.out.println("main-" + i);
        }
    }
}

// 1. 定义一个子类继承线程类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.info("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.info("B-" + i);
        }
    }
}

 3.2 多线程的创建方式二:实现Runnable接口

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

优缺点
 优点:任务类只是实现接口,可以继续继承其他类、实现其他接口,扩展性强。
 缺点:需要多一个Runnable对象。
public class Demo1 {
    public static void main(String[] args) {
        //需求:创建两个线程,分别用于打印10个A和10个B,最后观察下输出顺序

        //2. 创建任务类对象
        ARunnable aRunnable = new ARunnable();
        BRunnable bRunnable = new BRunnable();
        //3. 把任务类对象交给Thread处理
        Thread thread1 = new Thread(aRunnable);
        Thread thread2 = new Thread(bRunnable);
        //4. 调用线程对象的start()方法启动线程
        thread1.start();
        thread2.start();
    }
}
class ARunnable implements Runnable{
    public static final Logger LOGGER = LoggerFactory.getLogger("ARunnable");
    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            LOGGER.info("A-" + i);
        }
    }
}
class BRunnable implements Runnable{
    public static final Logger LOGGER = LoggerFactory.getLogger("BRunnable");
    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            LOGGER.info("B-" + i);
        }
    }
}

3.3 多线程的创建方式三:实现Callable接口

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

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

FutureTask的API

FutureTask提供的构造器说明
public FutureTask<>(Callable call)把Callable对象封装成FutureTask对象。
FutureTask提供的方法说明
public V get() throws Exception获取线程执行call方法返回的结果。
public class Demo1 {

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

        // 创建Callable的对象
        OddTask oddTask = new OddTask();
        EvenTask evenTask = new EvenTask();
        // 创建FutureTask的对象
        FutureTask<Integer> oddFutureTask = new FutureTask<>(oddTask);
        FutureTask<Integer> evenFutureTask = new FutureTask<>(evenTask);
        // 把FutureTask对象交给Thread对象
        //创建线程对象
        Thread oddThread = new Thread(oddFutureTask);
        Thread evenThread = new Thread(evenFutureTask);
        //调用线程的start方法
        oddThread.start();
        evenThread.start();
        // 获取线程执行call方法返回的结果
        Integer oddSum = oddFutureTask.get();
        Integer evenSum = evenFutureTask.get();
        // 在主线程中再做个汇总,得到总和
        System.out.println("奇数的和为:"+oddSum);
        System.out.println("偶数的和为:"+evenSum);
        System.out.println("总和为:"+(oddSum+evenSum));


    }
}
//计算100之内的奇数的和,并返回
class OddTask implements Callable<Integer>{// 泛型,表示返回的结果类型

    @Override
    public Integer call() throws Exception {
        int sum = 0;
        for (int i = 1; i <= 100; i+=2) {
            sum += i;
        }
        return sum;
    }
}
//计算100之内的偶数的和,并返回
class EvenTask implements Callable<Integer>{

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

三种线程的创建方式对比

方式优点缺点
继承Thread类编程比较简单,可以直接使用Thread类中的方法扩展性较差,不能再继承其他的类,不能返回线程执行的结果
实现Runnable接口扩展性强,实现该接口的同时还可以继承其他的类。编程相对复杂,不能返回线程执行的结果
实现Callable接口扩展性强,实现该接口的同时还可以继承其他的类。可以得到线程执行的结果编程相对复杂

3.4 Thread类的方法

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()...让调用当前这个方法的线程先执行完!
Thread提供的常见构造器说明
public Thread(String name)可以为当前线程指定名称
public Thread(Runnable target)封装Runnable对象成为线程对象
public Thread(Runnable target, String name)封装Runnable对象成为线程对象,并指定线程名称
public class Demo1 {

    //需求: 通过下面任务,我们来学习sleep和join方法
    //1. 创建A、B两个线程类,分别打印1~5
    //2. 在主线程序中创建A、B两个子线程
    //3. 在主线程序中开启A、B两个子线程
    //4. 让A线程每打印一次,都要暂停3秒钟
    //5. B线程要等A线程打印完毕,再开始打印
    public static void main(String[] args) throws InterruptedException {
        
        //2. 在主线程序中创建A、B两个子线程
        AThread aThread = new AThread();
        BThread bThread = new BThread();

        //3.1 在主线程序中开启子线程A
        aThread.start();
        //5. B线程要等A线程打印完毕,再开始打印
        aThread.join();
        //3.2 在主线程序中开启子线程B
        bThread.start();

    }
}
//1. 创建A、B两个线程类,分别打印1~5
class AThread extends Thread {
    @Override
    public void run() {
        for (int i = 1; i <= 5; i++) {
            System.out.println("A线程打印了" + i);
            try {
                //4. 让A线程每打印一次,都要暂停3秒钟
                Thread.sleep(3000);//重写父类方法,父类不能抛出异常,子类也不可以,只能try-catch
            }catch (InterruptedException e){
                e.printStackTrace();
            }
        }
    }
}

class BThread extends Thread {
    @Override
    public void run() {
        for (int i = 1; i <= 5; i++) {
            System.out.println("B线程打印了" + i);
        }
    }
}

标签:String,配置文件,对象,void,Thread,线程,day10,多线程,public
From: https://blog.csdn.net/qq_58478983/article/details/142108515

相关文章

  • C++ 多线程详解:从基础到应用
    目录一、什么是多线程?二、C++中的多线程支持三、总结在现代应用中,多线程成为了提升程序性能的重要工具。特别是当我们希望充分利用多核CPU的计算能力时,C++提供了强大的多线程支持,可以并发地执行多个任务。今天,我们将通过易懂的讲解与实际的代码示例,帮助你掌握C+......
  • JAVA多线程-如何保证线程安全
    线程安全:指在多线程对一个共享资源同时进行操作时,所得到的结果都是一样的如何保证线程安全方法:要保证线程安全,就必须保证线程同步,保证线程的可见性,有序性,和原子性线程同步线程同步的含义和字面意思相反,同步其实是线程"排队"的意思,就是让线程按照一定的顺序执......
  • java多线程转换文件格式
    privatestaticfinalintTHREAD_COUNT=4;//线程数privatestaticfinalintBUFFER_SIZE=1024;//缓冲区大小/***多线程读取文件,转换文件编码格式4线程1Mb缓存**@paraminputFile输入文件Stringinput="E:/02code/web/test.txt"......
  • Java学习 - 多线程第二部分
    1.线程池1.1线程状态介绍当线程被创建并启动以后,它既不是一启动就进入了执行状态,也不是一直处于执行状态。线程对象在不同的时期有不同的状态。那么Java中的线程存在哪几种状态呢?Java中的线程状态被定义在了java.lang.Thread.State枚举类中,State枚举类的源码如下:publi......
  • 多线程模拟叫号看病
    //普通号publicclassNormalThreadextendsThread{privateintnum=20;publicintgetNum(){returnnum;}publicvoidsetNum(intnum){this.num=num;}publicNormalThread(Stringname,intnum){super(......
  • 使用 Parallel 类进行多线程编码(下)
    2.Parallel.ForEach()的使用 从ForEach()这个名字可以看出该方法是用来遍历泛型集合的,新建一个ASP.NETCore Web应用的项目,如下:         在Index.cshtml.cs文件中增加一个UserInfo.cs的类,代码如下:publicclassUserInfo{publicint......
  • Numba最近邻插值(CPU+ GPU + Z轴切块 + XYZ轴切块 + 多线程)
    文章目录最近邻插值(加速方法)(1)scipy.ndimage.zoom(2)Numba-CPU加速(3)Numba-GPU加速(4)Numba-CPU加速(Z轴切块)(5)Numba-CPU加速(XYZ轴切块)(6)Numba-CPU加速(XYZ轴切块)+多线程输入数据插值倍数时耗scipy.ndimage.zoom(1024,1024,512)4172.16sNumba-CPU(1024,1024,512)456.58sN......
  • 二、并发编程与多线程-2.2、多线程(中)
    2.2、多线程(中)2.2.4、为什么启动线程不能直接调用run()方法?调用两次start()方法会有什么后果?答:在Java中,启动线程不能直接调用run()方法的原因是,run()方法是线程的执行体,通过调用start()方法来启动线程可以创建一个新的线程并使其运行。如果直接调用run()方法,则会在当前线......
  • python读配置文件配置信息
    在Python中,读取配置文件常用的库有configparser和yaml。以下是使用configparser读取INI格式配置文件的例子:首先是配置文件config.ini的内容:  [database]user=myuserpassword=mypasswordhost=localhostdb_name=mydatabase [server]port=8080接......
  • C++ 多线程代码性能分析——Oracle Developer Studio工具教程
        最近写项目的时候,为了提升性能,把原来一些单线程的代码改成了并行运行。这里我用到的用于评估性能提升效果的工具是OracleDeveloperStudio,不过刚上手时,发现网上相关的教程和博客较少,有些功能的使用也是摸索着过来的,这一过程可谓是十分痛苦了……如今距离初次接触......