Day18-【Java SE进阶】多线程

一、线程

1. 什么是线程?

  • 线程(Thread)是一个程序内部的一条执行流程。
  • 程序中如果只有一条执行流程,那这个程序就是单线程的程序。

2. 多线程

  • 多线程是指从软硬件上实现的多条执行流程的技术(多条线程由CPU负责调度执行)

3. 如何在程序中创建出多条线程?

Java是通过java.lang.Thread 类的对象来代表线程的。

3.1 线程创建方式一:继承Thread类
package com.test;

/**
 * 目标:掌握线程的创建方式一:集成Thread类
 */
public class LogBackTest {
    public static void main(String[] args) {
        //main方法由一条磨人的主线程负责执行
        //3.创建线程类的对象代表一个线程
        Thread myThread = new MyThread();
        //4.启动线程(自动执行run方法)
        myThread.start();//main线程 t线程
        for (int i = 0; i < 6; i++) {
            System.out.println("主线程"+i);
        }
    }
}

/**
 * 1.让子类继承Thread类
 */
class MyThread extends Thread{
    //2.必须重写Thread类的run方法
    @Override
    public void run() {
        for (int i = 0; i < 5; i++) {
            System.out.println("Mythread线程输出"+i);
        }
    }
}

在这里插入图片描述
多线程的注意事项
1、启动线程必须是调用star方法,不是调用run方法。
2、不要把主线程任务放在启动子线程之前。


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

在这里插入图片描述

package com.test;

public class Thread2 {
    public static void main(String[] args) {
        //3. 创建任务对象
        Runnable myRun = new MyRun();
        //4. 把任务对象交给一个线程对象处理
        new Thread(myRun).start();
        for (int i = 0; i < 6; i++) {
            System.out.println("主线程"+i);
        }
    }
}

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

线程创建方式二的匿名内部类写法

  • 可以创建Runnable的匿名内部类对象。
  • 再交给Thread线程对象。
  • 再调用线程对象的start()启动线程。
package com.test;

public class ThreadTest1 {
    public static void main(String[] args) {
        Runnable myThread = new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 100; i++) {
                    System.out.println("子线程一" + i);
                }
            }
        };
        new Thread(myThread).start();
        
        //简化形式1:
        new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 100; i++) {
                    System.out.println("子线程二" + i);
                }
            }
        }).start();
        
        //简化形式2:
        new Thread(()->{for (int i = 0; i < 100; i++) {
            System.out.println("子线程三" + i);
        }}).start();
        
        for (int i = 0; i < 100; i++) {
            System.out.println("主线程"+i);
        }
    }
}

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

前两种线程创建方式都存在的一个问题

  • 假如线程执行完毕后有一些数据需要返回,他们重写的run方法均不能直接返回结果。

怎么解决这个问题?
JDK5.0提供了Callable接口和FutureTask类来实现(多线程的第三种创建方式)

在这里插入图片描述

package com.test;

import javax.print.DocFlavor;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

public class ThreadTest3 {
    public static void main(String[] args) throws Exception {
        //3、创建一个Callble对象
        Callable<String> myCallable = new MyCallable(100);
        //4、把Callbale的对象封装成一个FutureTask对象(任务对象)
        //未来任务对象的作用
        //是一个任务对象,实现了Runnable对象
        //可以在线程执行完毕之后,用未来任务对象调用get方法获取线程执行完毕后的结果
        FutureTask<String> f1 = new FutureTask<>(myCallable);
        //5、把任务对象交给一个Thread对象
        new Thread(f1).start();
        //6、获取线程执行完毕后返回的结果
        //注意:如果执行到这儿,加入上面的线程还没有执行完毕,这里的代码会暂停,等待上面线程执行完毕后才会获取结果
        String s = f1.get();
        System.out.println(s);
    }
}

/**
 * 1、让这个类实现Callable接口
 */
class MyCallable implements Callable{
    private int n;
    MyCallable(){}
    MyCallable(int n){
        this.n=n;
    }
    //2、重写call方法
    @Override
    public String call() throws Exception {
        //描述线程的任务,返回线程执行的结果
        int sum=0;
        for (int i = 0; i <= this.n; i++) {
            sum+=i;
        }
        return ""+sum;
    }
}


在这里插入图片描述
在这里插入图片描述

package com.test;

import sun.awt.windows.ThemeReader;

/**
 * 目标:掌握线程的创建方式一:集成Thread类
 */
public class LogBackTest {
    public static void main(String[] args) {
        //main方法由一条磨人的主线程负责执行
        //3.创建线程类的对象代表一个线程
        Thread t1 = new MyThread("我是卡卡西");
        MyThread t2 = new MyThread("我是小乔");
        //4.启动线程(自动执行run方法)
//        t1.setName("1号线程");
        t1.start();//main线程 t线程
        System.out.println(t1.getName());
//        t2.setName("2号线程");
        t2.start();
        System.out.println(t2.getName());

        //主线程对象的名字
        //哪个线程执行它,它就会得到哪个线程对象。
        Thread thread = Thread.currentThread();
        thread.setName("牛逼线程");
        System.out.println(thread.getName());
        for (int i = 0; i < 1; i++) {
            System.out.println("主线程的输出"+i);
        }
    }
}

/**
 * 1.让子类继承Thread类
 */
class MyThread extends Thread{
    MyThread(){}
    MyThread(String name){
        super(name);
    }
    //2.必须重写Thread类的run方法
    @Override
    public void run() {
        Thread thread = Thread.currentThread();
        for (int i = 0; i < 1; i++) {
            System.out.println(thread.getName()+"线程输出"+i);
        }
    }
}

package com.test;

public class ThreadTest4 {
    public static void main(String[] args) throws InterruptedException {
        for (int i = 0; i < 6; i++) {
            System.out.println(i);
            if(i==3){
                //会让当前执行的线程暂停2s,再继续执行
                //项目经理让我加上这行代码,如果用户交钱了,我就注释掉!
                Thread.sleep(2000);
            }
        }

        //join方法作用:让当前调用这个方法的线程先执行完
        MyThread t1 = new MyThread();
        t1.start();
        t1.join();

        MyThread t2 = new MyThread();
        t2.start();
        t2.join();

        MyThread t3 = new MyThread();
        t3.start();
        t3.join();
    }
}

Thread其他方法的说明
Thread类还提供了诸如:yield、interrupt、守护线程、线程优先级等线程的控制方法,在开发中很少使用,这些方法会后续需要用到的时候再讲解。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/516304.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

全局统一返数据类型封装记录

全局统一返回值封装 ​ 在Spring Boot中&#xff0c;实现全局统一返回值封装是一种常见的做法&#xff0c;它有助于保持API的一致性&#xff0c;并简化前端对响应数据的处理。创建一个响应体类&#xff0c;包含状态码、消息、数据等字段。这个类可以作为所有控制器返回值的通用…

51入门之数码管

目录 1.数码管硬件简介 1.1数码管位选 1.2数码管数选 2.静态数码管显示 3.动态数码管显示 1.数码管硬件简介 数码管&#xff0c;在我们生活中无处不在&#xff0c;红绿灯的倒计时&#xff0c;电梯的显示屏&#xff0c;还有电子表的时间显示&#xff0c;都使用了数码管的相应原…

大厂面试之【Redis持久化机制】 - RDB和AOF概述及应用配置

文章目录 Redis持久化1. RDB(Redis DataBase)1.1 概述1.2 配置应用 2. AOF(Append Only File)2.1 概述2.2 配置应用 Redis持久化 先上结论&#xff1a;Redis持久化操作分为rdb以及aof&#xff0c;但是前者已经够用 1. RDB(Redis DataBase) 1.1 概述 rdb保存的是dump.rdb文件在指…

31. UE5 RPG使用增强输入激活GameplayAbility(一)

在前面文章中&#xff0c;我们实现了对技能添加并直接激活功能&#xff0c;介绍了GA的相关参数配置。现在&#xff0c;我们还不能通过键位触发技能&#xff0c;正常在游戏时&#xff0c;我们需要通过键位触发技能&#xff0c;实现技能的激活。 在UE5里面添加了增强输入&#xf…

modprobe加载驱动模块时报错:modprobe: module xxx.ko not found in modules.dep

问题 使用modprobe时&#xff0c;报错modprobe: module xxx.ko not found in modules.dep&#xff1a; 原因 加载模块时&#xff0c;依赖没法正确添加 解决 在使用modprobe前&#xff0c;调用一下depmod指令&#xff0c;之后再用modprobe加载驱动模块 depmod modprobe interr…

使用Autodl与Xftp远程训练模型及管理远程文件

1 AutoDL网站登录创建实例 AutoDL网站:AutoDL算力云 | 弹性、好用、省钱。租GPU就上AutoDL 1&#xff09;进入算力市场&#xff0c;选取可用显卡&#xff08;工作日一般白天抢不到&#xff0c;晚上才能抢到&#xff09; 2&#xff09;选择配置环境 3&#xff09;创建成功实例…

基于ArrayList实现简单洗牌

前言 在之前的那篇文章中&#xff0c;我们已经认识了顺序表—>http://t.csdnimg.cn/2I3fE 基于此&#xff0c;便好理解ArrayList和后面的洗牌游戏了。 什么是ArrayList? ArrayList底层是一段连续的空间&#xff0c;并且可以动态扩容&#xff0c;是一个动态类型的顺序表&…

关于hive启动的相关问题记录

问题&#xff1a;初始化hive元数据报错 [atguiguhadoop102 software]$ schematool -initSchema -dbType mysql -verboseError: Table CTLGS already exists (state42S01,code1050) Closing: 0: jdbc:mysql://hadoop102:3306/metastore?useSSLfalse org.apache.hadoop.hive.me…

数据结构和算法:十大排序

排序算法 排序算法用于对一组数据按照特定顺序进行排列。排序算法有着广泛的应用&#xff0c;因为有序数据通常能够被更高效地查找、分析和处理。 排序算法中的数据类型可以是整数、浮点数、字符或字符串等。排序的判断规则可根据需求设定&#xff0c;如数字大小、字符 ASCII…

Linux文件管理,压缩/解压缩和vi编辑器

目录 一.linux文件管理 1.cat 2. head和tail 3.WC 4.grep 5.paste&#xff08;合并&#xff09; 二.压缩,解压缩 1.gzip bzip2 2.归档tar 3.zip 和unzip 三.vi编辑器 一.linux文件管理 1.cat 格式 &#xff1a;cat 选项 文件名 &#xff08;文件名可以是单…

哈佛大学商业评论 --- 第三篇:真实世界中的增强现实

AR将全面融入公司发展战略&#xff01; AR将成为人类和机器之间的新接口&#xff01; AR将成为人类的关键技术之一&#xff01; 请将此文转发给您的老板&#xff01; --- 本文作者&#xff1a;Michael E.Porter和James E.Heppelmann 虽然物理世界是三维的&#xff0c;但大…

软件杯 深度学习中文汉字识别

文章目录 0 前言1 数据集合2 网络构建3 模型训练4 模型性能评估5 文字预测6 最后 0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; 深度学习中文汉字识别 该项目较为新颖&#xff0c;适合作为竞赛课题方向&#xff0c;学长非常推荐&#xf…

代码随想录第30天|51. N皇后

51. N皇后 51. N 皇后 - 力扣&#xff08;LeetCode&#xff09; 代码随想录 (programmercarl.com) 这就是传说中的N皇后&#xff1f; 回溯算法安排&#xff01;| LeetCode&#xff1a;51.N皇后_哔哩哔哩_bilibili 按照国际象棋的规则&#xff0c;皇后可以攻击与之处在同一行…

mysql+keepalive+lvs搭建的数据库集群实验

前提条件&#xff1a;准备5台计算机&#xff0c;且网络互通 1、客户端 yum groups -y install mariadb-client ip 192.168.0.5 2、lvs1 yum-y install ipvsadm keepalived ip 192.168.0.1 keepalivedvip 192.168.0.215 /etc/hosts 解析192.168.0.1 主机名 3、lvs2 yum-y i…

大数据实验三-HBase编程实践

目录 一&#xff0e;实验内容 二&#xff0e;实验目的 三&#xff0e;实验过程截图及说明 1、安装HBase 2、配置伪分布式模式&#xff1a; 3、使用hbase的shell命令来操作表&#xff1a; 4、使用hbase提供的javaAPI来编程实现类似操作&#xff1a; 5、实验总结及心得体会…

uniApp使用uview对vuex的二次封装实现全局变量

1、uni-app目根目录新建’/store/index.js’&#xff0c;并复制如下内容到其中 2、uni-app目根目录新建’/store/ u . m i x i n . j s ′ &#xff0c;并复制如下内容到其中&#xff0c;由于 H X 某些版本的限制&#xff0c;我们无法帮您自动引入 " u.mixin.js&#xff0…

不堪大用的pow

【题目描述】 输出100&#xff5e;999中的所有水仙花数。若3位数ABC满足&#xff0c;则称其为水仙花 数。例如&#xff0c;所以153是水仙花数。 【题目来源】 刘汝佳《算法竞赛入门经典 第2版》习题2-1 水仙花数&#xff08;daffodil&#xff09; 题目很简单&#xff0c;…

指针的偏移遍历数组--指针和数组名的区别

1.指针取地址&#xff1a;可以是数组名&#xff0c;可以是数组首地址&arr[0] 2.指针偏移完后记得回到数组首地址 #include <stdio.h>int main(){int arr[3] {1,2,3};int *p;int i;p arr; // 数组名就是数组的首地址// p &arr[0] 数组的首地址就是首个元素…

二分答案跳石头游戏

步骤&#xff1a; 输入&#xff1a; 用户输入了三个整数&#xff0c;分别表示石头的总长度l&#xff0c;石头的数量n&#xff0c;以及最多可以撤去的石头数量m。 初始化石头位置数组&#xff1a; 创建一个长度为n2的数组arr&#xff0c;用于存储每块石头的位置。数组的第一项…

FreeRTOS作业day4

1.总结二进制信号量和计数型信号量的区别&#xff0c;以及他们的使用场景。 二进制信号量的数值只有0和1&#xff0c;用于共享资源的访问 计数型信号量的值一般是大于或者等于2&#xff0c;用于生产者和消费者模型 2.使用技术型信号量完成生产者和消费者模型实验。 void Sta…