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

news2024/11/15 4:52:25

目录

前言:

多线程的实现方式:

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执行权,使得其他线程有机会执行。

总结:

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

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

 

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

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

相关文章

百度网盘加速下载

下载网页插件可搜索各种奇葩工具 Tampermonkey 在线解析连接&#xff1a;https://api.94speed.com/web/ 工具下载&#xff1a;https://motrix.app/zh-CN/download 解析完成后发送到&#xff1a;motrix

LeetCode 626. 换座位

题目链接&#xff1a;LeetCode 626. 换座位 题目描述 表名&#xff1a;Seat 编写SQL查询来交换每两个连续的学生的座位号。如果学生的数量是奇数&#xff0c;则最后一个学生的id不交换。 按 id 升序 返回结果表。 查询结果格式如下所示。 示例1&#xff1a; 题目分析 如…

Ubuntu20.04安装MySQL8

Ubuntu20.04安装MySQL8 MySQL8下载 点击MySQL download下载官网&#xff0c;按照自己所需要的版本下载对应的MySQL版本&#xff0c;如下图 点击下载后在进行解压&#xff0c;大致文件如下所示 然后需要一次安装对应的.deb文件。普通.deb程序安装命令&#xff1a; dpkg -i …

前端:地图篇(一)

1、前言 在很多的出行程序中&#xff0c;都会使用到地图这一个功能&#xff0c;在实际的开发中我们也不会去开发一个自己的地图模型。如果自己开发一个地图模型&#xff0c;那么需要投入的成本、人力都是非常巨大的。所以我们很多网站和APP中使用的都是第三方的接口和JS&#…

本地部署 audiocraft

本地部署 audiocraft 1. 什么是 audiocraft2. Github 地址3. 安装 Miniconda34. 创建虚拟环境5. 部署 audiocraft6. 启动 MusicGen7. 访问 MusicGen 1. 什么是 audiocraft Audiocraft 是一个通过深度学习进行音频处理和生成的库。它具有最先进的 EnCodec 音频压缩器/分词器&am…

Java Selenium WebDriver 网页填报

一、windows环境安装配置 1.安装chrome浏览器 在“关于chrome”界面&#xff0c;查看浏览器版本号 2.下载chromeDriver 在https://registry.npmmirror.com/binary.html?pathchromedriver/下载对应版本的驱动&#xff08;如果浏览器版本过新&#xff0c;建议下载最接近的版…

day20-101. 对称二叉树

101. 对称二叉树 力扣题目链接 给定一个二叉树&#xff0c;检查它是否是镜像对称的。 思路 镜像对称必要的条件就是根节点的左右子树互相对称 左子树的左孩子 右子树的右孩子左子树的右孩子 右子树的左孩子 递归 使用递归前要确定递归的顺序&#xff0c;是前序、后序还…

N个实现水平垂直居中的方法

1 行内元素的水平垂直居中 1.1 单行文本 要实现行内元素的水平居中&#xff0c;只需把行内元素包裹在块级父层元素中&#xff0c;并且在父层元素CSS设置如下&#xff1a; <div class"box"><p>center</p> </div>.box{background-color: aq…

Docker Compose编排部署LNMP服务

目录 安装docker-ce 阿里云镜像加速器 文件 启动 安装docker-ce [rootlocalhost ~]# wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo --2023-08-03 18:34:32-- http://mirrors.aliyun.com/repo/Centos-7.repo 正在解析主机 m…

Set-up ESP-AT Environment on Windows using CMD

Before you start, the following environments need to be installed: Git BashPython environment, suggest Python version: 3.8.7. Please ensure the installation of Python v3.8 version environment, and remember to select the option “add to PATH” during the in…

MyBatis-基础操作-CRDU

前端页面展示提供对于数据的删除操作&#xff0c;后端为其实现 根据id删除数据&#xff08;D&#xff09; 具体的SQL语句 delete from emp where id 17; 接口方法 Delete("delete from emp where id #{id} ")public int DeleteByID(Integer id); 测试方法 Testpub…

数据结构--线性表2-2

目录 一、线性表例题&#xff1a; 二、分配动态内存&#xff1a; 1.动态创建一个空顺序表的算法&#xff1a; 2.动态顺序表的插入算法&#xff1a; 3.动态顺序表的删除 三、线性表的链式表示和实现 例题1&#xff1a;创建链表并插入26个字母 例题2&#xff1a;在链表中取…

伺服电机的三种控制方式与三闭环控制

&#xff08;项目&#xff09;FPGA双电机主从快速稳定控制实现 第一章 伺服电机的三种控制方式与三闭环控制 伺服电机的三种控制方式与三闭环控制 &#xff08;项目&#xff09;FPGA双电机主从快速稳定控制实现前言一、电机控制方式二、电机三个闭环负反馈PID控制系统三、三闭…

LeetCode513. 找树左下角的值

513. 找树左下角的值 文章目录 [513. 找树左下角的值](https://leetcode.cn/problems/find-bottom-left-tree-value/)一、题目二、题解方法一&#xff1a;递归法&#xff08;层序遍历&#xff0c;深度优先搜索&#xff09;**不足之处以及如何改进** 方法二&#xff1a;迭代 一、…

2023年08月在线IDE流行度最新排名

点击查看最新在线IDE流行度最新排名&#xff08;每月更新&#xff09; 2023年08月在线IDE流行度最新排名 TOP 在线IDE排名是通过分析在线ide名称在谷歌上被搜索的频率而创建的 在线IDE被搜索的次数越多&#xff0c;人们就会认为它越受欢迎。原始数据来自谷歌Trends 如果您相…

三、文件与路径

1、隐藏文件与非隐藏文件 1.1、概念 (1)隐藏文件默认情况下看不到&#xff0c;需要进行相应设置才能看到。非隐藏文件默认情况下就能看到 1.2、Windows中的文件 (1)非隐藏文件设置为隐藏文件。选中文件&#xff0c;鼠标右键→属性&#xff0c;勾选隐藏。 (2)产看隐藏文件。…

资产盘点设备包括哪些

根据资产管理系统的卡账表和计算机设备管理系统的验证&#xff0c;固定资产的账卡完成一致&#xff1b;根据上级领导机构发布的资产盘点标示&#xff0c;固定资产。低价值易耗品进行标签贴绑&#xff0c;完成帐实一致&#xff0c;真实反映本行固定资产实物情况。   RFID固定…

RocketMQ 事务消息

事务消息是 RocketMQ 的高级特性之一 。这篇文章&#xff0c;笔者会从应用场景、功能原理、实战例子三个模块慢慢为你揭开事务消息的神秘面纱。 1 应用场景 举一个电商场景的例子&#xff1a;用户购物车结算时&#xff0c;系统会创建支付订单。 用户支付成功后支付订单的状态…

论测试猿如何优雅的甩锅

测试猿&#xff0c;经常被江湖人戏称为“背锅侠”。 这个称呼是怎么来的呢&#xff1f;我们来追溯一下根源。 当产品上线后&#xff0c;有 bug&#xff1a; “测试为什么没有测试发现这个问题&#xff1f;肯定是测试的责任&#xff01;” 当产品上线后&#xff0c;用户反馈…

Windows server上用nginx部署vue3项目

Windows server上用nginx部署vue3项目 一、报错信息三、总结 一、报错信息 这里&#xff0c;nginx给出以下错误信息&#xff1a; Windows&#xff1a;nginx: [error] CreateFile() “/logs/nginx.pid“ failed (2: The system&#xff09; 经分析&#xff0c;造成上述错误的本…