【Java学习|黑马笔记|Day21】IO流综合练习,多线程|常用成员方法,守护线程、礼让线程、插入线程

发布于:2025-07-25 ⋅ 阅读:(22) ⋅ 点赞:(0)

【DAY22】

欢迎大家在评论区交流讨论,一起学习共同进步🕵🏻‍♀️

文章目录

    • 【DAY22】
      • 一.综合练习
        • 1)网络爬虫
        • 2)登录注册
      • 二.多线程
        • 1)概念
        • 2)并发和并行
        • 3)多线程的三种实现方式
        • 4.1)多线程中的常用成员方法
        • 4.2)线程的优先级
        • 4.3)守护线程
        • 4.4)礼让线程
        • 4.5)插入线程
        • 5)线程的生命周期

一.综合练习

1)网络爬虫

1.爬取姓氏名字

public class T1 {
    public static void main(String[] args) throws IOException {
        String familyName = "https://hanyu.baidu.com/shici/detail?pid=0b2f26d4c0ddb3ee693fdb1137ee1b0d&from=kg0";
        String boyName = "http://www.haoming8.cn/baobao/10881.html";
        String girlName = "http://www.haoming8.cn/baobao/7641.html";

        //2.爬取数据,把数据拼成字符串
        String fN = webCrawler(familyName);
        String bN = webCrawler(boyName);
        String gN = webCrawler(girlName);

        //3.用正则表达式把符合要求的数据取出来
        ArrayList<String> fL = getData(fN,"([\\u4e00-\\u9fa5]{4})(,|。)",1);
        ArrayList<String> bL = getData(bN,"([\\u4e00-\\u9fa5]{2})(、|。)",1);
        ArrayList<String> gL = getData(gN,"([\\u4e00-\\u9fa5]{2})( )",1);

        System.out.println(fL);

    }

    private static ArrayList<String> getData(String str, String regex,int index) throws IOException {
        ArrayList<String> list = new ArrayList<>();
        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(str);
        while(matcher.find()) {
            list.add(matcher.group(index));
        }
        return list;
    }

    public static String webCrawler(String net) throws IOException {
        //1.定义StringBuilder拼接爬取到的数据
        StringBuilder sb = new StringBuilder();
        //2.创建一个URL对象
        URL url = new URL(net);
        //3.链接网址
        URLConnection conn = url.openConnection();
        //4.读取数据
        InputStreamReader isr = new InputStreamReader(conn.getInputStream());
        int ch;
        while((ch = isr.read()) != -1) {
            sb.append((char)ch);
        }
        isr.close();
        return sb.toString();

    }
}

2.处理数据

//4.处理数据
    //姓氏:把四个拆开放到新的集合中
    ArrayList<String> xL  = new ArrayList<>();
    for (String str : fL) {
        for(int i = 0; i < str.length(); i++){
            char c = str.charAt(i);
            xL.add(c + "");//把char变成字符串
        }
    }
    //男名:去重
    ArrayList<String> mL = new ArrayList<>();
    for (String s : bL) {
        if(!mL.contains(s)){
            mL.add(s);
        }
    }
    //女名:去重
    ArrayList<String> wL = new ArrayList<>();
    for (String s : gL) {
        if(!wL.contains(s)){
            wL.add(s);
        }
    }
    System.out.println(wL);
}

3.组合名字

HashSet<String> bhs = new HashSet<>();
while(true){
    if(bhs.size() == Count){
        break;
    }
    Collections.shuffle(fN);
    Collections.shuffle(bN);
    bhs.add(fN.get(0) + bN.get(0));
}

糊涂包生成假数据

public class T1 {
    public static void main(String[] args) {
        String familyName = "https://hanyu.baidu.com/shici/detail?pid=0b2f26d4c0ddb3ee693fdb1137ee1b0d&from=kg0";
        String boyName = "http://www.haoming8.cn/baobao/10881.html";
        String girlName = "http://www.haoming8.cn/baobao/7641.html";

        String familNameStr = HttpUtil.get(familyName);
        String boyNameStr = HttpUtil.get(boyName);
        String girlNameStr = HttpUtil.get(girlName);

        List<String> familyNameTempList = ReUtil.findAll("([\\u4e00-\\u9fa5]{4})(,|。)",familNameStr,1);
        List<String> boyNameTempList = ReUtil.findAll("([\\u4e00-\\u9fa5]{2})(、|。)",boyNameStr,1);
        List<String> girlNameTempList = ReUtil.findAll("([\\\\u4e00-\\\\u9fa5]{2})( )",girlNameStr,1);

        //处理数据
        
        //生成数据
        

        //写出数据
        FileUtil.writeLines(list,"D://","UTF-8");

    }
}
2)登录注册

将正确的用户名和密码存入本地的txt文件

让用户键盘输入用户名和密码比较是否正确

//username=zhangsan%password=123
public class T1 {
    public static void main(String[] args) throws IOException {
        //1.读取正确的用户名和密码
        BufferedReader br = new BufferedReader(new FileReader("src\\1.txt"));
        String line = br.readLine();
        String[] userInfo = line.split("&");
        String[] arr1 = userInfo[0].split("=");
        String[] arr2 = userInfo[1].split("=");

        String rightUsername = arr1[0];
        String rightPassword = arr1[1];

        Scanner sc = new Scanner(System.in);
        System.out.println("请输入用户名");
        String username = sc.nextLine();
        System.out.println("请输入密码");
        String password = sc.nextLine();

        if(rightUsername.equals(username) && rightPassword.equals(password)){
            System.out.println("登陆成功");
        }else {
            System.out.println("登录失败");
        }
    }
}

二.多线程

1)概念

进程:每一个正在运行的软件都是一个进程,是程序的基本执行实体

线程:是操作系统能够进行运算调度的最小单位,被包含在进程中,是进程中的实际运行单位

作用:有了多线程就可以让程序同时做多件事情,提高效率

2)并发和并行

并发:在同一时刻,有多个指令在单个CPU上交替运行

并行:在同一时刻,有多条指令在多个CPU上同时进行

3)多线程的三种实现方式
  1. 继承Thread类的方式进行实现
  2. 实现Run那别了接口的方式进行实现
  3. 利用Callable接口和Future接口方式实现

法一

public class T1 {
    public static void main(String[] args) {
        //1.定义一个类继承Thread
        //2.重写run方法
        //3.创建子类的对象启动线程
        MyThread t1 = new MyThread();
        MyThread t2 = new MyThread();

        t1.setName("线程1");
        t2.setName("线程2");
        //开启线程
        t1.start();
        t2.start();
    }
}
public class MyThread extends Thread {
    @Override
    public void run() {
        //书写线程要执行的代码
        for (int i = 0; i < 100; i++) {
            System.out.println(getName() + "123");
        }

    }
}

法二

public class T1 {
    public static void main(String[] args) {
        //1.自己定义一个类实现Runnable接口
        //2.重写里面的run方法
        //3.创建自己的类的对象
        //4.创建一个Thread类对象
        Myrun mr = new Myrun();
        Thread t1 = new Thread(mr);
        Thread t2 = new Thread(mr);
        t1.setName("t1");
        t2.setName("t2");
        t1.start();
        t2.start();

    }
}
public class Myrun implements Runnable{
    @Override
    public void run() {
        //书写线程要执行的代码
        for (int i = 0; i < 100; i++) {
            //获取当前线程的对象
            Thread t = Thread.currentThread();
            System.out.println(t.getName() + "asdfg");
        }
    }

法三

public class T1 {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        //1.定义一个类MyCallable实现Callabe接口
        //2.重写里面的call方法(有返回值)
        //3.创建自己的类的对象(表示多线程要执行的任务)
        //4.创建FutureTask的对象(作用管理多线程运行的结果)
        //5.创建一个Thread类对象
        MyCallable mc = new MyCallable();
        FutureTask<Integer> ft = new FutureTask(mc);
        Thread t1 = new Thread(ft);
        t1.start();

        System.out.println(ft.get());

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

对比

在这里插入图片描述

4.1)多线程中的常用成员方法

在这里插入图片描述

public class T1 {
    public static void main(String[] args) {
        //细节:如果没有给线程设置名字,线程也有默认名字
        //     格式:Thread-X X为序号,从0开始
        MyThread t1 = new MyThread();
        MyThread t2 = new MyThread();

        t1.start();
        t2.start();
    }
}

///.............................................
public class MyThread extends Thread {
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            System.out.println(getName() + "@" + i);
        }
    }
}
public class T1 {
    public static void main(String[] args) {
        //细节:如果要给线程设置名字,可以用setName可以用构造方法
        MyThread t1 = new MyThread("飞机");
        MyThread t2 = new MyThread("坦克");

        t1.start();
        t2.start();
    }
}

//......................................................
public class MyThread extends Thread {
    public MyThread(String name) {
        super(name);
    }
    public MyThread() {

    }

    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            System.out.println(getName() + "@" + i);
        }
    }
}
//当JVM虚拟机启动之后,会自动的启动多条线程,其中一条线程叫做,=main线程,用来调用main方法并执行里面的代码
4.2)线程的优先级

抢占式调度:随机

public class T1 {
    public static void main(String[] args) {
        
        MyThread t1 = new MyThread("飞机");
        MyThread t2 = new MyThread("坦克");

        System.out.println(t1.getPriority());//默认优先级是5
        System.out.println(t2.getPriority());

        t1.setPriority(1);//最高10 最低1
        t2.setPriority(10);//优先级更高抢到CPU的概率越高

        t1.start();
        t2.start();
    }
}
4.3)守护线程
public class T1 {
    public static void main(String[] args) {
        //当非守护线程执行完毕后,守护线程就会陆续结束
        MyThread t1 = new MyThread("飞机");
        MyThread t2 = new MyThread("坦克");

        //把第二个线程设置为守护线程
        t2.setDaemon(true);

        t1.start();
        t2.start();
    }
4.4)礼让线程
public class MyThread extends Thread {
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            System.out.println(getName() + "@" + i);
            //表示出让当前CPU的执行权
            Thread.yield();
        }
    }
}
4.5)插入线程
public class T1 {
    public static void main(String[] args) throws InterruptedException {

        MyThread t1 = new MyThread("飞机");

        t1.start();

        //把t1这个线程插入到当前线程之前
        //等t1线程全部执行完再执行别的
        t1.join();

        //执行在main线程中的
        for (int i = 0; i < 10; i++) {
            System.out.println("main线程" + i);
        }

    }
}
5)线程的生命周期

在这里插入图片描述


网站公告

今日签到

点亮在社区的每一天
去签到