【多线程】Java中多线程的几种实现方式

        

        多线程(multithreading)是指在一个程序中同时执行多个不同的线程(thread),每个线程都是程序的一部分,是独立的执行路径。相比于单线程程序,多线程程序可以更充分地利用计算机的多核心或多处理器资源,提高程序的运行效率和用户体验。在多线程编程中需要注意线程同步、锁、死锁等问题。

        常见的多线程实现方式有以下几种:

1、继承Thread类方式

        这种方式是定义一个类继承Thread类,然后重写run()方法,将要执行的任务写在run()方法中。创建线程实例后,调用start()方法启动线程。该方式实现简单,但如果类已经继承了其他类,则无法使用。

以下是一个继承Thread类的多线程案例:

class MyThread extends Thread {
    @Override
    public void run() {
        for (int i = 0; i < 5; i++) {
            System.out.println(Thread.currentThread().getName() + " " + i);
        }
    }
}

public class Main {
    public static void main(String[] args) {
        MyThread thread1 = new MyThread();
        MyThread thread2 = new MyThread();

        thread1.start();
        thread2.start();
    }
}

        这个案例中,我们创建了一个继承了Thread类的MyThread类,并在它的run方法中打印了当前线程的名字和一个循环计数器。然后在主函数中,我们创建了两个MyThread对象并启动它们。当程序运行时,两个线程会交替打印出它们的计数器值,因为它们是同时运行的。

        这个案例展示了如何继承Thread类来创建一个线程,并且启动线程的方法是调用start方法。每个线程都有自己的执行上下文,包含自己的栈空间和局部变量,因此两个线程之间的计数器值是相互独立的。

2、实现Runnable接口方式

        Java实现Runnable接口方式的代码如下:

  1. 定义一个类实现Runnable接口,重写run()方法
public class MyRunnable implements Runnable {
    @Override
    public void run() {
        // 编写线程执行的任务代码
        for (int i = 0; i < 10; i++) {
            System.out.println(Thread.currentThread().getName() + ": " + i);
        }
    }
}

  1. 创建MyRunnable实例并将其作为参数传入Thread类的构造方法中
public class Main {
    public static void main(String[] args) {
        MyRunnable myRunnable = new MyRunnable();
        Thread thread = new Thread(myRunnable);
        thread.start();
    }
}

  1. 启动线程并执行任务

        当调用Thread的start()方法时,JVM会自动调用MyRunnable实例的run()方法,从而执行线程的任务。

        注意:在这种方式下,多个线程可以共享同一个MyRunnable实例,这意味着多个线程可以同时执行同一个任务。如果需要多个线程执行不同的任务,需要为每个线程创建一个单独的Runnable实例,并将其传入Thread的构造方法中。

        这种方式是定义一个类实现Runnable接口,重写run()方法,将要执行的任务写在run()方法中。调用Thread类的构造函数,将该实现Runnable接口的对象作为参数传入,创建Thread实例后调用start()方法启动线程。该方式相比于继承Thread类方式,更加灵活,因为一个类可以实现多个接口。

3、实现Callable接口方式

        Callable接口是Java提供的一个线程执行结果的返回值接口,需要通过Future接口获取执行结果。下面是Java实现Callable接口的示例代码:

import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;

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

    public static void main(String[] args) throws Exception {
        MyCallable callable = new MyCallable();
        FutureTask<Integer> futureTask = new FutureTask<>(callable);
        Thread thread = new Thread(futureTask);
        thread.start();
        Integer result = futureTask.get();
        System.out.println("计算结果:" + result);
    }
}

        在上面的代码中,我们通过实现Callable接口,实现了call()方法,返回了一个Integer类型的结果。我们使用FutureTask类将Callable对象封装成一个异步任务,然后启动一个线程执行这个异步任务。最后,通过FutureTask的get()方法获取异步任务的执行结果。

        注意:FutureTask的get()方法会阻塞当前线程,直到异步任务执行完毕并返回结果。如果异步任务执行时间过长,会导致当前线程一直阻塞。为了避免这种情况,我们可以使用FutureTask的get(long timeout, TimeUnit unit)方法,设置一个超时时间,超过这个时间后如果异步任务还没有执行完毕,则抛出TimeoutException异常,当前线程继续执行。

        该方式类似于实现Runnable接口方式,但是需要实现Callable接口的call()方法,并返回一个结果。可以通过FutureTask类将Callable转换成Runnable来启动线程并获取返回值。

4、实现线程池方式

        Java中线程池可以通过以下步骤实现:

        1. 创建一个ExecutorService对象,它是Java中线程池的基本实现类之一,也是一个抽象类,可以使用Executors类中的静态方法来创建。

ExecutorService executorService = Executors.newFixedThreadPool(5);

        这里创建了一个固定大小为5的线程池。

        2. 在需要执行任务的地方,使用submit方法提交一个Runnable对象或Callable对象。

executorService.submit(new Runnable() {
    @Override
    public void run() {
        // 执行任务代码
    }
});

        3. 执行完任务后,记得关闭线程池。

executorService.shutdown();

线程池的好处在于它可以避免重复创建和销毁线程,从而提高了程序的性能和效率。同时,线程池还可以控制并发线程的数量,防止系统崩溃。

        通过使用线程池,可以更好地管理和复用线程,避免了线程的频繁创建和销毁。使用线程池是一种高效的多线程实现方式。

        每种方式都有各自的特点,需要根据具体的实际情况选择合适的方式。

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

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

相关文章

一拎即走的轻薄云台投影,极米投影仪Z7X解锁观影新姿势

近年来&#xff0c;随着投影技术的不断提高以及大屏幕带来的加倍快乐&#xff0c;让投影仪成为了一种新的观影潮流。尤其是“去客厅化”的大背景下&#xff0c;年轻人几乎将目光都投向了投影仪&#xff0c;从而实现在家就能享受大屏观影的效果和体验。那么备受当下年轻消费者青…

全套的外贸出口业务流程,赶紧收藏起来吧

很多做外贸的小伙伴入行遇到的第一个问题就是对外贸业务流程的不熟悉&#xff0c;今天小易给大家整理了一份外贸业务全流程&#xff0c;从开发客户到售后服务一整套流程&#xff0c;一起来看看吧&#xff01; 目前做外贸开发客户的渠道一般有以下几种&#xff1a; 1、自建站、外…

机器人运动控制:摩擦力矩补偿

问题描述 机器人运动控制中&#xff0c;摩擦力矩补偿是一个重要的环节。在机器人动力学模型中&#xff0c;重力和关节摩擦在低速运动时占主导因素&#xff0c;因此对机器人进行重力-摩擦补偿是机器人力控制中被广泛采用的方法。 库伦-粘滞摩擦模型是摩擦力辨识的常用方法&…

『亚马逊云科技产品测评』活动征文|基于亚马逊EC2云服务器安装Prometheus数据可视化监控

授权声明&#xff1a;本篇文章授权活动官方亚马逊云科技文章转发、改写权&#xff0c;包括不限于在 Developer Centre, 知乎&#xff0c;自媒体平台&#xff0c;第三方开发者媒体等亚马逊云科技官方渠道 亚马逊EC2云服务器&#xff08;Elastic Compute Cloud&#xff09;是亚马…

视频剪辑转码:mp4批量转成wmv视频,高效转换格式

在视频编辑和处理的领域&#xff0c;转换格式是一项常见的任务。在某些编辑和发布工作中&#xff0c;可能需要使用WMV格式。提前将素材转换为WMV可以节省在编辑过程中的时间和精力。从MP4到WMV的批量转换&#xff0c;不仅能使视频素材在不同的平台和设备上得到更好的兼容性&…

基于ssm校园自助洗衣系统的分析与设计论文

摘 要 互联网发展至今&#xff0c;无论是其理论还是技术都已经成熟&#xff0c;而且它广泛参与在社会中的方方面面。它让信息都可以通过网络传播&#xff0c;搭配信息管理工具可以很好地为人们提供服务。针对校园洗衣信息管理混乱&#xff0c;出错率高&#xff0c;信息安全性差…

Path的使用-path绘制折线的时候带上圆角

场景&#xff1a; 使用antv-g6 自定义边的时候&#xff0c;绘制折线&#xff0c;此时都是直角&#xff0c;需要加圆角&#xff0c;没找到属性&#xff0c;自己绘制&#xff1a; 最后使用了A&#xff08;elliptical Arc&#xff09;弧形 A命令用于画弧形。 A rx ry x-axis-r…

基于单个参数线性回归的机器学习代码

本文为学习吴恩达版本机器学习教程的代码整理&#xff0c;使用的数据集为https://github.com/fengdu78/Coursera-ML-AndrewNg-Notes/blob/f2757f85b99a2b800f4c2e3e9ea967d9e17dfbd8/code/ex1-linear%20regression/ex1data1.txt 将数据集和py代码放到同一目录中&#xff0c;使…

超参数优化的多功能贝叶斯优化包SMAC3

地址 关键词 Bayesian optimization, hyperparameter optimization, SMAC3 文章概述 本文介绍了SMAC3&#xff0c;一个用于超参数优化的多功能贝叶斯优化包。SMAC3使用随机森林作为代理模型&#xff0c;并结合了多样性的BO和强化策略&#xff0c;如积极竞赛和多样性方法…

如何使用DC电源模块进行快速原型开发

如何使用DC电源模块进行快速原型开发 BOSHIDA DC电源模块是一种用于转换电源电压的电子元件&#xff0c;它可以把输入的直流电压转换为不同的输出电压&#xff0c;让我们可以在无需改变设备硬件的情况下&#xff0c;实现电压的升降。它广泛应用于不同的电子设备中&#xff0c;…

【数字经济】你必须知道的SABOE数字化转型

【文末送书】今天推荐一本企业管理类前沿书籍《企业架构驱动数字化转型&#xff1a;以架构为中心的端到端转型方法论》 目录 01传统企业数字化转型面临诸多挑战02SABOE数字化转型五环法为企业转型破除迷雾03文末送书 01传统企业数字化转型面临诸多挑战 即将过去的2023年&#…

​ 轻量应用服务器:亚马逊云科技打造全球领先的云计算解决方案

随着“第四次工业革命”的爆炸式发展&#xff0c;众多企业都将自己的业务与迅速发展的应用开发和网站建设领域高度绑定。而对于众多有上云需求的企业和个人用户来说&#xff0c;选择一款自己的服务器配置就成为了一项至关重要的任务。而随着需求端的不断扩大&#xff0c;云服务…

SD-WAN VS MPLS :怎么选择最合适的网络连接方案?

随着企业网络需求的不断增长&#xff0c;网络连接方案也变得更加多样化。在这种情况下&#xff0c;SD-WAN和MPLS成为了企业考虑的两种主要选择。本文将就SD-WAN和MPLS这两种网络连接方案进行比较&#xff0c;深入探讨它们在成本、体验、部署周期和运维等方面的差异。 1、成本投…

050:vue项目webpack打包,大文件分成几个小文件的方法

第050个 查看专栏目录: VUE ------ element UI 专栏目标 在vue和element UI联合技术栈的操控下&#xff0c;本专栏提供行之有效的源代码示例和信息点介绍&#xff0c;做到灵活运用。 &#xff08;1&#xff09;提供vue2的一些基本操作&#xff1a;安装、引用&#xff0c;模板使…

[PTP][Announce] ClockIdentity 定义规则

文章目录 一、简介二、格式三、备注 一、简介 ClockIdentity: 时钟标识, 8个字节&#xff0c;采用IEEE MAC48编码方式 二、格式 PTP实例的clockIdentity值应符合802.1AS的8.5.2.2中的规定。 如下&#xff08;8.5.2.2中描述了1588-2019的内容&#xff09;&#xff1a; clockI…

城市生态与交通,数据可视化大屏,PSD源文件(ps大屏设计素材)

用酷炫的大屏展示其城市的生态与交通情况&#xff0c;辅助相关决策。好的大屏组件也可以让设计师的工作更加便捷&#xff0c;使其更高效快速的完成设计任务。现分享城市生态与交通的大屏Photoshop源文件&#xff0c;开箱即用&#xff01;以下为部分截图示意。 若需更多的 智慧…

HCIP---RSTP/MSTP

文章目录 目录 文章目录 前言 一.RSTP诞生背景 二.RSTP对比STP的快速收敛机制 端口角色变化 接口状态变化 RSTP-BPDU 指定端口- P/A机制 BPDU发送变化 端口状态快速切换 优化拓扑变更机制 三.MSTP MSTP诞生背景 MSTP相关概念 MSTP配置 总结 前言 STP协议虽然能够解决环…

Holynix

信息收集阶段 存活主机探测&#xff1a;arp-scan -l 当然了&#xff0c;正常来说我们不应该使用arp进行探测&#xff0c;arp探测的是arp的缓存表&#xff0c;我们应该利用nmap进行探测&#xff01; nmap -sT --min-rate 10000 192.168.182.0/24 端口探测 nmap -sT --min-rat…

java学习part42反射

187-反射机制-反射的理解与使用举例_哔哩哔哩_bilibili

代码随想录二刷 |二叉树 |94.二叉树的中序遍历

代码随想录二刷 &#xff5c;二叉树 &#xff5c;二叉树的中序遍历 题目描述解题思路代码实现迭代法递归法 题目描述 94.二叉树的中序遍历 给定一个二叉树的根节点 root &#xff0c;返回 它的 中序 遍历 。 示例 1&#xff1a; 输入&#xff1a;root [1,null,2,3] 输出&a…