【从零开始学习JAVA | 第三十八篇】应用多线程

目录

前言:

多线程的实现方式:

Thread常见的成员方法:

总结:


前言:

           多线程的引入不仅仅是提高计算机处理能力的技术手段,更是适应当前时代对效率和性能要求的必然选择。在本文中,我们将深入探讨多线程的应用和实践,帮助读者更好地理解和应用多线程技术,提升计算机的处理能力,迎接挑战的世界。"

多线程的实现方式:

        1.继承Thread类:你可以创建一个类并继承Thread类,然后重写run()方法,在run()方法中定义线程要执行的任务。通过创建该类的实例,并调用start()方法,可以启动一个新的线程执行run()方法中的任务。

示例代码:

class MyThread extends Thread {
    public void run() {
        // 定义线程要执行的任务
        System.out.println("线程执行任务");
    }
}

public class MainClass {
    public static void main(String[] args) {
        // 创建线程并启动
        MyThread thread = new MyThread();
        thread.start();
    }
}

        2.实现Runnable接口:你可以创建一个类实现Runnable接口,然后实现run()方法,再通过创建Thread对象,并将Runnable对象作为参数传递给Thread的构造函数,创建一个新的线程。

示例代码:

class MyRunnable implements Runnable {
    public void run() {
        // 定义线程要执行的任务
        System.out.println("线程执行任务");
    }
}

public class MainClass {
    public static void main(String[] args) {
        // 创建线程并启动
        MyRunnable runnable = new MyRunnable();
        Thread thread = new Thread(runnable);
        thread.start();
    }
}

        3.使用Executor框架:Java提供了Executor框架,它是高级线程管理的一种方式。通过Executor,你可以使用线程池来管理和执行多个线程任务,提供更好的线程控制和资源管理。

示例代码:

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class MainClass {
    public static void main(String[] args) {
        // 创建线程池
        ExecutorService executor = Executors.newFixedThreadPool(5);

        // 提交任务
        executor.execute(new Runnable(){
            public void run() {
                // 定义线程要执行的任务
                System.out.println("线程执行任务");
            }
        });

        // 关闭线程池
        executor.shutdown();
    }
}

         4.使用Callable 和 Future 接口方式实现:当需要在线程执行完毕后获取返回结果时,可以使用Callable和Future接口来实现多线程。Callable是一个带有返回结果的任务,可以通过call()方法执行任务并返回结果。Future表示一个异步执行的任务,可以通过get()方法获取任务的返回结果。

这种方式的优点就在于:可以获取多线程的执行结果 

示例代码:



class MyCallable implements Callable<Integer> {
    public Integer call() throws Exception {
        // 定义线程要执行的任务,并返回结果
        return 42;
    }
}

public class MainClass {
    public static void main(String[] args) {
        // 创建线程池
        ExecutorService executor = Executors.newSingleThreadExecutor();

        // 提交Callable任务
        Future<Integer> future = executor.submit(new MyCallable());

        // 等待并获取结果
        try {
            Integer result = future.get();
            System.out.println("线程执行任务的结果为: " + result);
        } catch (InterruptedException | ExecutionException e) {
            e.printStackTrace();
        }

        // 关闭线程池
        executor.shutdown();
    }
}

Thread常见的成员方法:

  • start(): 启动线程,使线程进入可运行状态,具体执行由操作系统调度。
  • run(): 线程执行的任务代码,通常通过重写该方法来定义线程要执行的逻辑。
  • sleep(long millis): 让当前线程休眠指定的毫秒数,暂停线程的执行。
  • join(): 等待线程执行完成,即等待线程终止。
  • yield(): 暂停当前正在执行的线程,并允许其他线程执行。
  • isAlive(): 判断线程是否还活着。
  • interrupt(): 中断线程,向线程发送一个中断信号,但并不一定终止线程的执行。
  • isInterrupted(): 判断线程是否被中断。
  • setName(String name): 设置线程的名称。
  • getName(): 获取线程的名称。
  • suspend(): 不推荐使用,暂停线程的执行。
  • resume(): 不推荐使用,恢复线程的执行。
  • setPriority(int priority): 设置线程的优先级,取值范围为1-10,默认为5。
  • getPriority(): 获取线程的优先级。
  • setDaemon(boolean on)设置为守护线程

我们再单独介绍一下几个常用并且不容易理解的成员方法:

1.setPriority(int priority)getPriority()

setPriority(int priority)方法用于设置线程的优先级,参数priority表示线程的优先级,取值范围为1-10,优先级默认为5。其中,1表示最低优先级,10表示最高优先级。

getPriority()方法用于获取线程的优先级,返回值为线程的优先级。

线程的优先级用于指定线程在竞争CPU资源时的优先级顺序。然而,优先级并不是绝对的执行顺序,仅作为建议给操作系统进行线程调度。

优先级的出现是因为我们JAVA中的线程在被CPU调度的时候,采用的是抢占式调度,也就是优先级越高,越容易抢到调度机会,而除了抢占式调度之外,我们还有非抢占调度,也就是CPU对线程轮流调度,不存在随机。

需要注意以下几点:

  1. 不同操作系统对线程优先级的处理可能有所不同。
  2. 线程的优先级不能保证一定按照预期执行,因为优先级可能受到操作系统调度算法的影响。
  3. 不应该过分依赖线程的优先级来实现业务逻辑,因为这可能导致代码的可移植性差。

一般来说,应用程序中使用默认优先级即可,除非有特殊需求。同时,应避免过于频繁地修改线程的优先级,以免导致优先级倾斜等问题。

2.setDaemon(boolean on)

setDaemon(boolean on)是Thread类提供的一个方法,用于设置线程的守护状态。当一个线程被设置为守护线程时,它会成为JVM中所有非守护线程的"服务员",在所有非守护线程结束后,JVM会自动退出,从而终止守护线程的执行。

具体来说,守护线程的特点如下:

  1. 守护线程通常用来提供后台服务或辅助功能,不影响程序的主要业务逻辑。
  2. 守护线程并不会影响JVM的正常终止,即使还有守护线程在执行,JVM也会自动退出。
  3. 当所有非守护线程结束后,守护线程会被自动终止,不会等待任务完成。

使用setDaemon(true)将线程设置为守护线程,使用setDaemon(false)将线程设置为用户线程(默认值)。

需要注意以下几点:

  1. setDaemon()方法只能在线程启动之前调用,一旦线程启动后,不能再修改守护状态。
  2. 守护线程不能持有任何可以独占资源的锁,因为它们可能会在任何时刻被终止,这样可能导致资源不正确释放或状态不一致的问题。
  3. 守护线程并不保证会执行完它们的任务,因此在编写守护线程时要特别小心,确保它们不会影响到程序的正确执行。

守护线程主要用于在后台提供服务或执行一些不断运行的任务,比如垃圾回收线程、定时任务线程等。一般情况下,我们在主线程中创建的线程都是用户线程,即非守护线程。

3.join()与yield()

join()与yield()都是用于线程的控制和协作的方法。

  1. join()

    • join()方法用于等待调用线程完成其执行,然后再继续执行当前线程。
    • 在一个线程A中调用另一个线程B的join()方法会使当前线程A阻塞,直到线程B执行完成。
    • 这通常用于多个线程之间的协作,确保某个线程在另一个线程执行完成后再继续执行。
    • 如果在join()方法中指定了超时时间,那么当前线程将等待指定的时间,如果超时仍未完成,则继续执行。
  2. yield()

    • yield()方法是线程的静态方法,它让出当前线程的执行权,将其暂停,以便其他具有相同或更高优先级的线程可以执行。
    • yield()的作用是提高线程的执行效率和响应性。
    • 当一个线程调用yield()方法后,它会从运行状态转变为就绪状态,让出CPU执行权,然后和其他具有相同或更高优先级的线程竞争CPU资源。
    • 注意,yield()方法并不能保证使得当前线程暂停执行,它只是提供一个提示给线程调度器,告知可以进行线程切换。

需要注意的是,join()方法可以用于线程的协作,而yield()方法用于线程的调度。join()方法会阻塞线程直到目标线程执行完成,而yield()方法会主动让出CPU执行权,使得其他线程有机会执行。

总结:

        本文我们介绍了使用线程的三种方法以及线程类中的常见成员方法,多线程是处理高并发问题的一个重要手段,因此我们一定要学好多线程。

如果我的内容对你有帮助,请点赞,评论,收藏。创作不易,大家的支持就是我坚持下去的动力!

 

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

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

相关文章

python+opencv实现显示摄像头,截取相关图片,录取相关视频

实时显示摄像头图像 按下空格键&#xff0c;截取图片 按下tab键&#xff0c;开始录制摄像内容&#xff0c;再次按下&#xff0c;结束录制 按下Esc键&#xff0c;关闭窗口 import cv2 import numpy#第几章图片 img_count0InitVideoFalse #第几个视频 video_count0 video_flagFa…

Mybatis实现JsonObject对象与JSON之间交互

项目中使用PostGresql数据库进行数据存储&#xff0c;表中某字段为Json类型&#xff0c;用于存储Json格式数据。PG数据库能够直接存储Json算是一大特色&#xff0c;很多特定情境下使用直接存储Json字段数据能够大量节省开发时间&#xff0c;提高后台数据查询和转换效率。 1、基…

文心一言 VS 讯飞星火 VS chatgpt (68)-- 算法导论6.5 7题

文心一言 VS 讯飞星火 VS chatgpt &#xff08;68&#xff09;-- 算法导论6.5 7题 七、试说明如何使用优先队列来实现一个先进先出队列&#xff0c;以及如何使用优先队列来实现栈(队列和栈的定义见 10.1 节。) 文心一言&#xff1a; 优先队列是一种数据结构&#xff0c;其中…

数据结构--单链表OJ题

上文回顾---单链表 这章将来做一些链表的相关题目。 目录 1.移除链表元素 2.反转链表 3.链表的中间结点 4.链表中的倒数第k个结点 5.合并两个有序链表 6.链表分割 7.链表的回文结构 8.相交链表 9.环形链表 ​编辑 10.环形链表II ​编辑 ​编辑 1.移除链表元素 思…

穷举深搜暴搜回溯剪枝(3)

一)字母大小写全排列 784. 字母大小写全排列 - 力扣&#xff08;LeetCode&#xff09; 1)从每一个字符开始进行枚举&#xff0c;如果枚举的是一个数字字符&#xff0c;直接忽视 如果是字母的话&#xff0c;进行选择是变还是不变 2)当进行遍历到叶子结点的时候&#xff0c;直接将…

安装skywalking并集成到微服务项目

文章目录 一、前言二、介绍1. 架构 三、安装skywalking服务端四、启动skywalking服务端五、微服务项目开发注册中心网关服务商品服务订单服务支付服务测试 六、下载java客户端七、微服务集成skywalking客户端1. idea启动2. 命令行启动3. 集成效果 八、skywalking客户端配置1. 配…

淘宝资源采集(从零开始学习淘宝数据爬取)

1. 为什么要进行淘宝数据爬取&#xff1f; 淘宝数据爬取是指通过自动化程序从淘宝网站上获取数据的过程。这些数据可以包括商品信息、销售数据、评论等等。淘宝数据爬取可以帮助您了解市场趋势、优化您的产品选择以及提高销售额。 淘宝作为全球的电商平台&#xff0c;每天都有…

Flutter:gsy_flutter_demo项目学习——布局切换动画、列表滑动监听、列表滑动到指定位置、高斯模糊

前言 gsy_flutter_demo是一个关于各种小案例和小问题的方案解决。项目是由flutter大佬恋猫de小郭维护的 项目地址&#xff1a;https://github.com/CarGuo/gsy_flutter_demo 感兴趣的可以看一下大佬的文章&#xff1a;Flutter完整开发实战详解系列&#xff0c;GSY Flutter 系…

Excel中——日期列后添加星期

需求&#xff1a;在日期列中添加星期几&#xff1f; 第一步&#xff1a;打开需要添加星期的Excel文件&#xff0c;在日期后面添加日期 第二步&#xff1a;选择日期列&#xff0c;点击鼠标右键&#xff0c;在下拉列表中&#xff0c;选择“设置单元格格式” 第三步&#xff1a; 在…

【数据分析】Numpy (一)

目录 1.Numpy简介&#xff1a; Numpy用途&#xff1a; 2.Numpy的简单使用&#xff1a; 2.1导入Numpy&#xff1a; 2.1查看numpy的版本&#xff1a; ​编辑3.NumPy - Ndarray 对象 3.1ndarray属性&#xff1a; 3.2 numpy.array参数构造 3.3创建numpy数组&#xff1a; 3.4num…

以指标驱动,保险、零售、制造企业开启精益敏捷运营的新范式

近日&#xff0c;以“释放数智生产力”为主题的 Kyligence 用户大会在上海前滩香格里拉大酒店成功举行。大会包含上午的主论坛和下午的 4 场平行论坛&#xff0c;并举办了闭门会议、Open Day 等活动。来自金融、零售、制造、医药等行业的客户及合作伙伴带来了超过 23 场主题演讲…

微信小程序wx.getlocation接口权限申请总结

先附上申请通过截图 插播内容&#xff1a;可代开通&#xff0c;保证通过。wx.getLocation接口&#xff08;获取当前的地址位置&#xff09; qq&#xff1a; 308205428 如何申请 当申请微信小程序的wx.getLocation接口权限时&#xff0c;你可以…

华为PMS API client token auth failed

对接华为pms时出现问题&#xff0c;提示华为PMS API client token auth failed 主要是权限的问题&#xff0c;创建项目的时候选择N/A

上海市第十人民医院胃肠外科沈通一:以菌为药,非药而愈

6月29日&#xff0c;2023主动健康与临床营养高峰论坛在西安国际会展中心盛大召开&#xff0c;会议汇集了来自国内医学与营养领域杰出的专家学者&#xff0c;交流分享行业的先进理念和研究成果&#xff0c;为主动营养业界与学界能量交换搭建了新接口&#xff0c;以凝聚学术力量&…

采购分析:节省采购成本的 6 种方法

为了成功启动采购计划、稳定现金流并节省开支&#xff0c;企业需要了解从采购到付款的 P2P 周期的方方面面。 有远见的采购领导者将采购分析作为综合战略的一部分。因其有助于以简化和自动化的方式解决问题&#xff0c;从而更好地管理项目并节省大量成本。 什么是采购分析&am…

jenkins gitlab多分支构建发布

内容背景介绍 这个是新手教程,普及概念为主 公司现在还使用单分支发布测试环境和生产,多人协同开发同一个项目导致测试环境占用等待等情况 测试环境占用等待问题 测试环境代码直接合并到 master,容易导致误发布到生产的情况 避免多版本同时发布测试不完善的情况出现 中间件…

Rust dyn - 动态分发 trait 对象

dyn - 动态分发 trait 对象 dyn是关键字&#xff0c;用于指示一个类型是动态分发&#xff08;dynamic dispatch&#xff09;&#xff0c;也就是说&#xff0c;它是通过trait object实现的。这意味着这个类型在编译期间不确定&#xff0c;只有在运行时才能确定。 practice tr…

Node.js-http模块服务端请求与响应操作,请求报文与响应报文

简单案例创建HTTP服务端&#xff1a; // 导入 http 模块 const http require("http"); // 创建服务对象 const server http.createServer((request, response) > {// 设置编码格式&#xff0c;解决中文乱码问题response.setHeader("content-type", &…

MySQL安装详细教程!!!

安装之前&#xff0c;先卸载你之前安装过的数据库程序&#xff0c;否则会造成端口号占用的情况。 1.首先下载MySQL:MySQL :: Download MySQL Community Server(下载路径) 2.下载版本不一样&#xff0c;安装方法略有不同&#xff1b;&#xff08;版本5的安装基本一致&#xff0c…

启动Flink显示初始化状态怎么解决?

启动Flink显示初始化状态怎么解决&#xff1f; Flink On Yarn模式 问题 flnk任务在跑的过程中&#xff0c; 有时候任务停掉了 &#xff0c;不过我有 定时任务&#xff0c;可以把失败的flink任务拉起来&#xff0c;但是因为最新的checkpoint做失败了&#xff0c;导致脚本无法拉…