多线程JUC:多线程的实现和常用成员方法(守护、礼让、插入线程)

news2024/9/24 8:56:24

👨‍🎓作者简介:一位大四、研0学生,正在努力准备大四暑假的实习
🌌上期文章:首期文章
📚订阅专栏:多线程&JUC
希望文章对你们有所帮助

JUC的学习也是需要一些计算机、操作系统的知识的,也算是比较重要的吧,其实自己也是接触了不少的,包括之前做Redis的项目的时候也是老摸这些玩意。但是还没有非常系统的学过,为了即将到来的面试,JUC抓紧速成一波。

多线程的实现和常用成员方法

  • 实现多线程
    • 继承Thread类
    • 实现Runnable接口
    • 利用Callable和Future接口
    • 总结
  • 多线程的常用成员方法
    • 线程优先级
    • 守护线程
    • 礼让线程
    • 插入线程

实现多线程

继承Thread类

将类声明为Thread类的子类,该子类应重写Thread类的new方法,接下来就可以分配并启动该子类的实例,开启一个线程。

这里实现一个简单的Demo:
1、创建Thread类的子类:

public class MyThread extends Thread{
    @Override
    public void run() {
        //线程要执行的代码
        for (int i = 0; i < 100; i++) {
            System.out.println(this.getName() + "Hello World!");
        }
    }
}

2、创建对象开启实例,观察结果:

public class ThreadDemo {
    public static void main(String[] args) {
        MyThread t1 = new MyThread();
        MyThread t2 = new MyThread();

        //给线程起名字,方便观察运行结果
        t1.setName("线程1");
        t2.setName("线程2");

        //开启线程
        t1.start();
        t2.start();
    }
}

最终运行结果显示线程1和线程2是并行执行,而不是串行的了。

实现Runnable接口

先自己定义一个类,这个类实现了Runnable接口,并重写run方法。接着在测试类中创建这个类的对象,再创建一个Thread类的对象,并开启线程。

1、定义MyRun类并实现Runnable接口,由于这个类没有继承Thread类,所以不能使用getName方法,但是Thread类本身具有静态方法currentThread可以获取当前在执行任务的线程的对象,因此可以通过这个对象来执行getName方法:

public class MyRun implements Runnable{
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            //获取当前线程的对象
            Thread thread = Thread.currentThread();
            System.out.println(thread.getName() + "Hello World");
        }
    }
}

2、测试类中创建该类的对象、Thread类的对象,并开启线程:

public class ThreadDemo {
    public static void main(String[] args) {
        //创建MyRun的对象,表示多线程要执行的任务
        MyRun mr = new MyRun();
        //创建线程对象,并setName
        Thread t1 = new Thread(mr);
        t1.setName("线程1");
        Thread t2 = new Thread(mr);
        t2.setName("线程2");
        //开启线程
        t1.start();
        t2.start();
    }
}

利用Callable和Future接口

第三种实现方式实际上是对前面两种方法的补充。
前面两种实现方式都重写了run,但是其没有返回值,我们就无法获取多线程运行的结果。
第三种实现方式的特点就是可以获取多线程运行结果

其实现的流程:

1、创建一个MyCallable类实现Callable接口
2、重写call方法,方法是有返回值的,表示多线程运行的结果
3、编写测试类:
(1)创建MyCallable对象表示多线程要执行的任务
(2)创建Future对象,该对象可以管理多线程运行的结果,由于Future是一个接口无法创建对象,所以要创建其实现类FutureTask的对象
(3)创建Thread对象,再开启线程

1、MyCallable类:

public class MyCallable implements Callable<Integer> {

    @Override
    public Integer call() throws Exception {
        //求1-100之间的和
        int sum = 0;
        for (int i = 0; i <= 100; i++) {
            sum += i;
        }
        return sum;
    }
}

2、测试类:

public class ThreadDemo {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        //创建MyRun的对象,表示多线程要执行的任务
        MyCallable mc = new MyCallable();
        //创建FutureTask对象
        FutureTask<Integer> ft = new FutureTask<>(mc);
        //创建线程对象
        Thread t = new Thread(ft);
        //开启线程
        t.start();
        Integer result = ft.get();
        System.out.println(result);
    }
}

总结

1、继承Thread:
(1)优点:变成简单,可以直接使用Thread类中的方法
(2)缺点:可拓展性差,不能再继承其他的类
2、实现Runnable接口:
(1)优点:拓展性强,实现该接口的同时还能继承其他的类
(2)编程相对复杂,不能直接使用Thread类中的方法
3、实现Callable接口:
(1)除了Runnable接口的优点,还可以观察线程运行的结果
(2)编程相对复杂,不能直接使用Thread类中的方法

多线程的常用成员方法

下面是多线程常用的一些成员方法,其实很多也都是见过的:

方法名称说明
String getName()返回线程名称
void setName(String name)设置线程名,也可以使用构造方法
static Thread currentThread()获取当前线程对象
static void sleep(long time)让线程休眠指定的时间,单位为毫秒
setPriority(int newPriority)设置线程优先级
final int getDaemon(boolean on)设置为守护线程
public static void yield()礼让线程
public static void join()插入进程

对于前4种方法,有一些注意点和细节:

1、若没有给线程设置名字,使用getName也是会有默认的名字的,格式为Thread-X(X为序号,从0开始),可以自行去底层看一下
2、除了可以用setName可以给线程设置名字,也可以使用构造函数MyThread t = new MyThread("线程");,但是需要保证MyThread里面的构造函数内部使用super关键字,从而重写父类的构造方法。
3、如果我们没有启动线程,执行Thread.currntThread(),也可以获取到线程,这个线程的名称即为main,即JVM虚拟机启动以后,会自动启动多条线程,其中有一条就是main线程,作用是调用main方法,并执行里面的代码
4、sleep():
(1)哪条线程执行到这个方法,哪条线程就睡眠
(2)方法的参数就表示睡眠的时间,单位为毫秒
(3)当时间到了以后,线程会自动被唤醒,继续执行下面的代码

线程优先级

首先需要了解一下操作系统中的系统调度,调度分为抢占式调度和非抢占式调度,在java虚拟机中采用的是抢占式调度,因此可以给线程设置优先级,优先级越大,抢占到CPU、被执行的概率就越大。
线程的优先级可以设置为1-10,默认为5。
在这里插入图片描述
注意:

1、可以使用getPriority来获取线程的优先级
2、优先级越高只能代表该线程被执行的概率越大,而不代表一定会被执行

守护线程

守护线程这个名称听起来不是很好理解,可以想象成是一个备胎线程,当其他的非守护线程执行完毕后,守护线程其实根本没有执行的必要了,会陆续的结束。将线程设置为守护线程调用t.setDaemon(true)即可。
这其实还是有应用场景的,比如QQ中的聊天和发送文件可以视为2个线程,当我们把聊天的线程关闭了以后,线程2就没有执行的必要了,就会自动终止。

礼让线程

我们之前设置了两个线程来执行相同的任务,可以发现两个线程确实是交替执行的,但是经常会出现线程1连续输出了好多内容这种情况,出现的原因就是因为线程的执行是有概率性的,而礼让线程表示将当前CPU的执行权出让:

public class MyThread extends Thread{
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            System.out.println(this.getName());
            //出让当前CPU的执行权
            Thread.yield();
        }
    }
}

但这里也只能尽量让结果均衡,但是还是可能会出现那种情况,所以这种方法用的少。

插入线程

观察下面的代码:

MyThread t = new MyThread();
t.setName("土豆");
t.start();
for(int i = 0; i < 10 ; ++i) {
	System.out.println("main线程" + i);
}

最后执行会先执行main线程,毕竟执行的就是main函数。
而使用join方法就可以将其插入到main线程之前,使得其先被执行:

t.join();//把t线程插入到当前线程之前,在这里当前线程就是main线程

这个方法用的也不多,只需要了解一下就好了。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【算法设计与分析】求根节点到叶节点数字之和

&#x1f4dd;个人主页&#xff1a;五敷有你 &#x1f525;系列专栏&#xff1a;算法分析与设计 ⛺️稳中求进&#xff0c;晒太阳 题目 给你一个二叉树的根节点 root &#xff0c;树中每个节点都存放有一个 0 到 9 之间的数字。 每条从根节点到叶节点的路径都代表一个数…

高可用 k8s 1.29 一键安装脚本, 丝滑至极

博客原文 文章目录 集群配置配置清单集群规划集群网络规划 环境初始化主机配置 配置高可用ApiServer安装 nginx安装 Keepalived 安装脚本需要魔法的脚本不需要魔法的脚本配置自动补全加入其余节点 验证集群 集群配置 配置清单 OS&#xff1a; ubuntu 20.04kubernetes&#xf…

HarmonyOS class类对象基础使用

按我们之前的写法 就是 Entry Component struct Dom {p:Object {name: "小猫猫",age: 21,gf: {name: "小小猫猫",age: 18,}}build() {Row() {Column() {// ts-ignoreText(this.p.gf.name)}.width(100%)}.height(100%)} }直接用 Object 一层一层往里套 这…

MySQL用心总结

大家好&#xff0c;好久不见&#xff0c;今天笔者用心一步步写一份mysql的基础操作指南&#xff0c;欢迎各位点赞收藏 -- 启动MySQL net start mysql-- 创建Windows服务 sc create mysql binPath mysqld_bin_path(注意&#xff1a;等号与值之间有空格) mysql -h 地址 -…

【Flink状态管理(二)各状态初始化入口】状态初始化流程详解与源码剖析

文章目录 1. 状态初始化总流程梳理2.创建StreamOperatorStateContext3. StateInitializationContext的接口设计。4. 状态初始化举例&#xff1a;UDF状态初始化 在TaskManager中启动Task线程后&#xff0c;会调用StreamTask.invoke()方法触发当前Task中算子的执行&#xff0c;在…

如何从 iPhone 上恢复永久删除的照片

您的 iPhone 上缺少照片吗&#xff1f;讽刺的是&#xff0c;iPhone 的许多高级功能可能正是这个问题如此普遍的原因。幸运的是&#xff0c;还有很多方法可以从 iPhone 恢复已删除的照片&#xff0c;具体取决于您设备的设置方式。 本文涵盖了所有这些内容。该过程根据您的具体情…

git安装配置

1、下载安装 下载地址 2、配置git用户 git config --global user.name "yw" git config --global user.email "88888qq.com" 3、git init 初始化 4、生成ssh密钥 mkdir .ssh //创建文件夹cd .ssh //进入新建文件夹 ssh-keygen -t rsa // 输入密钥文…

计算机服务器中了halo勒索病毒如何处理,halo勒索病毒解密数据恢复

网络技术的不断发展与应用&#xff0c;为企业的生产生活提供了极大便利&#xff0c;但网络数据安全威胁无处不在&#xff0c;近日&#xff0c;云天数据恢复中心接到某连锁超市求助&#xff0c;企业计算机服务器被halo勒索病毒攻击&#xff0c;导致计算机系统瘫痪&#xff0c;无…

将xyz格式的GRACE数据转成geotiff格式

我们需要将xyz格式的文件转成geotiff便于成图&#xff0c;或者geotiff转成xyz用于数据运算&#xff0c;下面介绍如何实现这一操作&#xff0c;采用GMT和matlab两种方法。 1.GMT转换 我们先准备一个xyz文件&#xff0c;这里是一个降水文件。在gmt中采用以下的语句实现xyz转grd…

【Spring】GoF 之工厂模式

一、GoF 23 设计模式简介 设计模式&#xff1a;一种可以被重复利用的解决方案 GoF&#xff08;Gang of Four&#xff09;&#xff0c;中文名——四人组 《Design Patterns: Elements of Reusable Object-Oriented Software》&#xff08;即《设计模式》一书&#xff09;&…

TCP 传输控制协议

1 TCP 1.1 TCP 最主要的特点 1.TCP 是面向连接的运输层协议。 2.每一条 TCP 连接只能有两个端点 (endpoint)&#xff0c;每一条 TCP 连接只能是点对点的&#xff08;一对一&#xff09;。 3.TCP 提供可靠交付的服务。 4.TCP 提供全双工通信。 5.面向字节流 TCP 中的“流…

【Qt】Android上运行keeps stopping, Desktop上正常

文章目录 问题 & 背景背景问题 解决方案One More ThingTake Away 问题 & 背景 背景 在文章【Qt】最详细教程&#xff0c;如何从零配置Qt Android安卓环境中&#xff0c;我们在Qt中配置了安卓开发环境&#xff0c;并且能够正常运行。 但笔者在成功配置并完成上述文章…

Git、github与gitee码云

1.git核心是两个仓库&#xff1a;本地仓库和远程仓库 主要用于团队合作和代码版本控制&#xff08;个人现有版本代码出错可回溯上个提交版本的代码&#xff09; 远程仓库国际主流githut&#xff0c;但外网速度问题&#xff0c;国内可使用码云gitee github&#xff1a;https:…

Springboot拦截器中跨域失效的问题、同一个接口传入参数不同,一个成功,一个有跨域问题、拦截器和@CrossOrigin和@Controller

Springboot拦截器中跨域失效的问题 一、概述 1、具体场景 起因&#xff1a; 同一个接口&#xff0c;传入不同参数进行值的修改时&#xff0c;一个成功&#xff0c;另一个竟然失败&#xff0c;而且是跨域问题拦截器内的request参数调用getHeader方法时&#xff0c;获取不到前端…

CSS:九宫格布局

九宫格布局效果如下&#xff1a; HTML 结构&#xff1a; <div class"container"><div class"item">1</div><div class"item">2</div><div class"item">3</div><div class"item&q…

机器学习系列——(十六)回归模型的评估

引言 在机器学习领域&#xff0c;回归模型是一种预测连续数值输出的重要工具。无论是预测房价、股票价格还是天气温度&#xff0c;回归模型都扮演着不可或缺的角色。然而&#xff0c;构建模型只是第一步&#xff0c;评估模型的性能是确保模型准确性和泛化能力的关键环节。本文…

【力扣】快乐数,哈希集合 + 快慢指针 + 数学

快乐数原题地址 方法一&#xff1a;哈希集合 定义函数 getNext(n) &#xff0c;返回 n 的所有位的平方和。一直执行 ngetNext(n) &#xff0c;最终只有 2 种可能&#xff1a; n 停留在 1 。无限循环且不为 1 。 证明&#xff1a;情况 1 是存在的&#xff0c;如力扣的示例一…

(十八)springboot实战——spring securtity注解方式的授权流程源码解析

前言 在上一节内容中&#xff0c;我们介绍了如何在FilterSecurityInterceptor过滤器中处理用户的授权流程&#xff0c;并分析了其源码&#xff0c;spring security还提供了方法级别的授权方式&#xff0c;通过EnableMethodSecurity注解启用权限认证流程&#xff0c;只需要在方…

每日一题——LeetCode1422.分割字符串的最大得分

方法一 暴力枚举 枚举所有分割点的情况&#xff0c;取最大得分 var maxScore function(s) {let res 0;const n s.length;for (let i 1; i < n; i) {let score 0;for (let j 0; j < i; j) {if (s[j] 0) {score;}}for (let j i; j < n; j) {if (s[j] 1) {sco…

分享86个行业PPT,总有一款适合您

分享86个行业PPT&#xff0c;总有一款适合您 86个行业PPT下载链接&#xff1a;https://pan.baidu.com/s/1avbzwqK8ILLWYIOylK1aRQ?pwd8888 提取码&#xff1a;8888 Python采集代码下载链接&#xff1a;采集代码.zip - 蓝奏云 学习知识费力气&#xff0c;收集整理更不易…