Java进阶篇--创建线程的四种方式

目录

继承Thread类

扩展小知识:

Thread类的常见方法

Thread 类的静态方法

实现Runnable接口

使用Callable和Future创建线程

使用Executor框架创建线程池


继承Thread类

  1. 创建一个继承自Thread类的子类,并重写其run()方法,将相关逻辑实现,run()方法就是线程要执行的业务逻辑方法。
  2. 创建自定义的线程子类对象
  3. 调用子类实例的star()方法来启动线程

为了更好地理解单线程和多线程的执行过程,接下来通过一个图例分析一下单线程和多线程的区别。

从上图可以看出,单线程的程序在运行时,会按照代码的调用顺序执行,而在多线程中,main()方法和MyThread类的run()方法却可以同时运行,互不影响,这正是单线程和多线程的区别。

示例代码如下:

class MyThread extends Thread {
    public void run() {
        // 线程执行的代码逻辑
        System.out.println(Thread.currentThread().getName() +"线程正在运行");
    }
}
public class Main {
    public static void main(String[] args) {
        // 创建线程并启动
        MyThread thread = new MyThread();
        thread.start();
        System.out.println(Thread.currentThread().getName() + " main()方法执行结束");
    }
}

运行结果:

main main()方法执行结束
Thread-0线程正在运行

扩展小知识:

Thread类的常见方法

  1. start(): 启动线程,并使其进入可运行状态,当CPU调度到该线程时,会自动调用其run()方法开始执行线程代码。
  2. run(): 线程的执行逻辑,通常需要在子类中重写该方法以定义具体的线程行为。通过调用start()方法来启动线程时,系统会自动调用该方法。
  3. sleep(long millis): 让当前线程暂停执行指定的时间(以毫秒为单位),进入阻塞状态。暂停期间不占用CPU时间,其他线程可以继续执行。
  4. join(): 当一个线程A调用另一个线程B的join()方法时,线程A将会等待线程B执行完毕后才继续执行。
  5. getName(): 获取线程的名称。
  6. setName(String name): 设置线程的名称。
  7. getId(): 获取线程的唯一标识符。
  8. isAlive(): 判断线程是否存活,即线程是否已启动但尚未终止。
  9. setPriority(int priority): 设置线程的优先级,优先级范围为1-10,默认为5。优先级较高的线程在竞争资源时有更大的概率优先执行。
  10. yield(): 暂停当前正在执行的线程,并让出CPU资源给其他具有相同优先级的线程。仅是一种建议,不保证有效,具体是否产生效果取决于系统的调度器。
  11. interrupt(): 中断线程,给线程发送中断信号。线程在合适的时候可以检查到该中断请求,然后自行决定如何响应。
  12. isInterrupted(): 判断线程是否被中断,返回布尔值。
  13. static boolean interrupted(): 判断当前线程是否被中断,并清除中断状态。

Thread 类的静态方法

currentThread() 是 Thread 类的静态方法,它返回当前正在执行的线程对象。具体来说,它返回一个表示当前线程的 Thread 对象。

可以使用 Thread.currentThread() 来获取当前线程的引用。这个方法常用于需要获得当前执行线程对象的场景,例如需要在运行时获取线程的名称、线程优先级、判断线程是否被中断等操作。

注意:currentThread() 是 Thread 类的静态方法,因此可以直接通过 Thread.currentThread() 的方式调用,不需要创建 Thread 对象实例。

下面是一个示例代码,演示如何使用 currentThread() 方法:

public class Main {
    public static void main(String[] args) {
        // 获取当前线程对象
        Thread currentThread = Thread.currentThread();

        // 获取当前线程的名称
        String threadName = currentThread.getName();
        System.out.println("当前线程名称:" + threadName);//当前线程名称:main

        // 获取当前线程的优先级
        int threadPriority = currentThread.getPriority();
        System.out.println("当前线程优先级:" + threadPriority);//当前线程优先级:5

        // 判断当前线程是否被中断
        boolean isInterrupted = currentThread.interrupted();
        System.out.println("当前线程是否被中断:" + isInterrupted);//当前线程是否被中断:false
    }
}

注意:getPriority() 方法是 Thread 类的实例方法,用于获取线程的优先级。该方法返回一个表示线程优先级的整数值。

线程优先级的范围是从 1 到 10,默认优先级为 5。较大的优先级值意味着线程更重要或更紧急,但并不保证高优先级的线程总是比低优先级的线程先执行。

实现Runnable接口

  1. 创建一个类实现Runnable接口,并重写其run()方法。
  2. 然后创建Thread对象,并将该实现Runnable接口的类的实例作为参数传递给Thread构造函数。
  3. 最后调用Thread对象的start()方法启动线程。

注意,实现 Runnable 接口相比直接继承 Thread 类具有更好的灵活性和可扩展性,因为它允许多个线程共享相同的 Runnable 实例。

下面是一个实现 Runnable 接口的示例代码:

class MyRunnable implements Runnable {
    @Override
    public void run() {
        // 在此处添加想要线程执行的代码逻辑
        System.out.println("线程运行中");
    }
}
public class Main {
    public static void main(String[] args) {
        // 创建 MyRunnable 实例
        MyRunnable myRunnable = new MyRunnable();

        // 创建 Thread 对象并传入 MyRunnable 实例
        Thread thread = new Thread(myRunnable);

        // 启动线程
        thread.start();
    }
}

使用Callable和Future创建线程

  1. 创建一个实现Callable接口的类,并重写其call()方法。
  2. 然后使用ExecutorService提交Callable任务,并通过Future对象获取返回结果。

注意:使用 Callable 和 Future 创建线程相比直接使用 Runnable 接口和 Thread 类更为灵活,因为它允许获得线程的执行结果,并能够异步地处理任务。

下面是使用 Callable 和 Future 创建线程的示例代码: 

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

public class Main implements Callable<String> {
    @Override
    public String call() {
        // 在此处添加想要线程执行的代码逻辑
        return "线程运行结束";
    }

    public static void main(String[] args) throws Exception {
        // 创建 CallableExample 实例
        Main callableExample = new Main();

        // 创建线程池
        ExecutorService executor = Executors.newSingleThreadExecutor();

        // 提交 CallableExample 实例到线程池并返回 Future 对象
        Future<String> future = executor.submit(callableExample);

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

        // 获取线程执行结果
        String result = future.get();
        System.out.println("线程结果: " + result);//线程结果: 线程运行结束

    }
}

使用Executor框架创建线程池

Executors提供了一系列工厂方法用于创先线程池,返回的线程池都实现了ExecutorService接口。

主要有newFixedThreadPool,newCachedThreadPool,newSingleThreadExecutor,newScheduledThreadPool。

注意,调用 shutdown() 方法后,线程池将不再接受新的任务,并且会等待已提交的任务执行完成。

使用 Executor 框架可以更方便地管理和控制线程池,避免手动创建和启动线程的繁琐操作。

下面是使用 Executor 框架创建线程池的示例代码:

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

public class Main {
    public static void main(String[] args) {
        // 创建固定大小的线程池,最多同时执行两个线程
        ExecutorService executor = Executors.newFixedThreadPool(2);

        // 提交任务到线程池
        executor.submit(new MyTask("任务1"));
        executor.submit(new MyTask("任务2"));
        executor.submit(new MyTask("任务3"));

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

    static class MyTask implements Runnable {
        private String name;

        public MyTask(String name) {
            this.name = name;
        }

        @Override
        public void run() {
            System.out.println("任务 " + name + " 正在执行");
        }
    }
}

执行结果

任务 任务2 正在执行
任务 任务1 正在执行
任务 任务3 正在执行

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

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

相关文章

EG3D: Efficient Geometry-aware 3D Generative Adversarial Networks [2022 CVPR]

长期以来&#xff0c;仅使用单视角二维照片集无监督生成高质量多视角一致图像和三维形状一直是一项挑战。现有的三维 GAN 要么计算密集&#xff0c;要么做出的近似值与三维不一致&#xff1b;前者限制了生成图像的质量和分辨率&#xff0c;后者则对多视角一致性和形状质量产生不…

mmdetection基于 PyTorch 的目标检测开源工具箱 入门教程

安装环境 MMDetection 支持在 Linux&#xff0c;Windows 和 macOS 上运行。它需要 Python 3.7 以上&#xff0c;CUDA 9.2 以上和 PyTorch 1.8 及其以上。 1、安装依赖 步骤 0. 从官方网站下载并安装 Miniconda。 步骤 1. 创建并激活一个 conda 环境。 conda create --name…

windows中安装sqlite

1. 下载文件 官网下载地址&#xff1a;https://www.sqlite.org/download.html 下载sqlite-dll-win64-x64-3430000.zip和sqlite-tools-win32-x86-3430000.zip文件&#xff08;32位系统下载sqlite-dll-win32-x86-3430000.zip&#xff09;。 2. 安装过程 解压文件 解压上一步…

Hystrix: Dashboard流监控

接上两张服务熔断 开始搭建Dashboard流监控 pom依赖 <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocat…

“R语言+遥感“水环境综合评价方法

详情点击链接&#xff1a;"R语言遥感"水环境综合评价方法 一&#xff1a;R语言 1.1 R语言特点&#xff08;R语言&#xff09; 1.2 安装R&#xff08;R语言&#xff09; 1.3 安装RStudio&#xff08;R语言&#xff09; &#xff08;1&#xff09;下载地址 &…

ChatGPT在高等教育中的应用利弊探讨

​人工智能在教育领域的应用日益广泛。2022年11月OpenAI开发的聊天机器人ChatGPT在全球范围内流传开来&#xff0c;其中用户数量最多的国家是美国(15.22%)。由于ChatGPT应用广泛&#xff0c;具有类似人类回答问题的能力&#xff0c;它正在成为许多学生和教育工作者的可信赖伙伴…

Unity——DOTween插件使用方法简介

缓动动画既是一种编程技术&#xff0c;也是一种动画的设计思路。从设计角度来看&#xff0c;可以有以下描述 事先设计很多基本的动画样式&#xff0c;如移动、缩放、旋转、变色和弹跳等。但这些动画都以抽象方式表示&#xff0c;一般封装为程序函数动画的参数可以在使用时指定&…

【80天学习完《深入理解计算机系统》】第十一天 3.4 跳转指令

专注 效率 记忆 预习 笔记 复习 做题 欢迎观看我的博客&#xff0c;如有问题交流&#xff0c;欢迎评论区留言&#xff0c;一定尽快回复&#xff01;&#xff08;大家可以去看我的专栏&#xff0c;是所有文章的目录&#xff09;   文章字体风格&#xff1a; 红色文字表示&#…

【FreeRTOS】【应用篇】任务管理相关函数

文章目录 前言一、函数解析1. 任务挂起 vTaskSuspend()① 使用场景② 设计思路③ 代码 2. 任务恢复 vTaskResume()① 作用② 设计思路③ 代码 3. 挂起任务调度器 vTaskSuspendAll()① 作用② 代码 4. 恢复任务调度器 xTaskResumeAll()① 设计思路② 代码 5. 任务删除函数 vTask…

人脸识别平台批量导入绑定设备的一种方法

因为原先平台绑定设备是通过一个界面进行人工选择绑定或一个人一个人绑定设备。如下&#xff1a; 但有时候需要在几千个里选择出几百个&#xff0c;那这种方式就不大现实了&#xff0c;需要另外一种方法。 目前相到可以通过导入批量数据进行绑定的方式。 一、前端 主要是显示…

Linux操作系统--克隆虚拟机

1.概述 我们在搭建大数据或者是集群的过程中,需要使用到许多配置相同或者相类似的环境。这一个时候就需要使用到克隆虚拟机的功能。 2.克隆虚拟机过程 (1).从现有虚拟机(关机状态)克隆出新虚拟机,右键选择管理=>克隆,如下所示 (2).直接点击下一步。如下所示 (3).选择…

Android Studio中引入MagicIndicator

1.github中下载文件 GitHub - hackware1993/MagicIndicator: A powerful, customizable and extensible ViewPager indicator framework. As the best alternative of ViewPagerIndicator, TabLayout and PagerSlidingTabStrip —— 强大、可定制、易扩展的 ViewPager 指示器框…

【Unity3D赛车游戏】【五】Unity中汽车加速效果是如何优化的?

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;元宇宙-秩沅 &#x1f468;‍&#x1f4bb; hallo 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍&#x1f4bb; 本文由 秩沅 原创 &#x1f468;‍&#x1f4bb; 收录于专栏&#xff1a;Uni…

Python如何进行基本的数学运算

Python进行基本的数学运算 Python是一门功能强大且易于学习的编程语言&#xff0c;它不仅可以用于开发应用程序&#xff0c;还可以用于执行各种数学运算。让我们一起来看看如何在Python中进行基本的数学运算。 加法、减法、乘法和除法 Python支持常见的加法、减法、乘法和除…

Linux操作系统--包管理yum

1.概述 YUM(全称为 Yellow dog Updater, Modified)是一个在 Fedora 和 RedHat 以及 CentOS中的 Shell 前端软件包管理器。基于 RPM 包管理,能够从指定的服务器自动下载 RPM 包并且安装,可以自动处理依赖性关系,并且一次安装所有依赖的软件包,无须繁琐地一次次下载、安装。…

Redis数据结构全解析【超详细万字分析】

文章目录 前言一、SDS1、SDS的必要性2、SDS的数据结构3、SDS的优势O&#xff08;1&#xff09;复杂度获取字符串长度二进制安全不会发生缓冲区溢出节省空间 二、链表1、结构设计2、优缺点 三、压缩列表1、结构设计2、连续更新3、压缩列表的缺陷 四、哈希表1、结构设计2、哈希冲…

开发新能源的好处

风能无论是总装机容量还是新增装机容量&#xff0c;全球都保持着较快的发展速度&#xff0c;风能将迎来发展高峰。风电上网电价高于火电&#xff0c;期待价格理顺促进发展。生物质能有望在农业资源丰富的热带和亚热带普及&#xff0c;主要问题是降低制造成本&#xff0c;生物乙…

深入分析负载均衡情景

本文出现的内核代码来自Linux5.4.28&#xff0c;为了减少篇幅&#xff0c;我们尽量不引用代码&#xff0c;如果有兴趣&#xff0c;读者可以配合代码阅读本文。 一、有几种负载均衡的方式&#xff1f; 整个Linux的负载均衡器有下面的几个类型&#xff1a; 实际上内核的负载均衡…

C#_委托详解

委托是什么&#xff1f; 字面理解&#xff1a;例如A要建一栋别墅&#xff0c;找到B建筑施工队&#xff0c;请B来建筑别墅。 委托类型规定方法的签名&#xff08;方法类型&#xff09;&#xff1a;返回值类型、参数类型、个数、顺序。 委托变量可以用来存储方法的引用&#x…

基于微信小程序的垃圾分类系统设计与实现(2.0 版本,附前后端代码)

博主介绍&#xff1a;✌程序员徐师兄、7年大厂程序员经历。全网粉丝30W、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ 1 简介 视频演示地址&#xff1a; 基于微信小程序的智能垃圾分类回收系统&#xff0c;可作为毕业设计 小…