Java创建多线程的几种方式详解

进程与线程

简单介绍下基础概念
进程:在内存中执行的应用程序
线程:进程中最小的执行单元,作用是负责当前进程中程序的运行。一个进程中至少有一个线程,一个进程还可以有多个线程,这样的应用程序就称之为多线程程序

下面介绍下创建多线程的几种方式

一、通过继承Thread类来实现

  1. 定义一个类,继承Thread
  2. 重写run方法,在run方法中设置线程任务(所谓的线程任务指的是此线程要干的具体的事儿,具体执行的代码)
public class MyThread extends Thread{
    @Override
    public void run() {
        for (int i = 0; i < 20; i++) {
            System.out.println("我的线程执行了"+i);
        }
    }
}
  1. 创建自定义线程类的对象
  2. 调用Thread中的start方法,开启线程,jvm自动调用run方法
public class Test {
    public static void main(String[] args) {
        MyThread t1 = new MyThread();//创建线程对象
        //调用start方法,开启线程,jvm自动调用run方法
        t1.start();
        for (int i = 0; i < 10; i++) {
            System.out.println("main线程执行了"+i);
        }
    }
}

二、实现Runnable接口

  1. 创建类,实现Runnable接口
  2. 重写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. 利用Thread类的构造方法:Thread(Runnable target),创建Thread对象(线程对象),将自定义的类当参数传递到Thread构造中,这一步是让我们自己定义的类成为一个真正的线程类对象
  2. 调用Thread中的start方法,开启线程,jvm自动调用run方法
public class Test {
    public static void main(String[] args) {
        MyRunnable myRunnable = new MyRunnable();
        Thread t1 = new Thread(myRunnable); //Thread(Runnable target)
        t1.start();//调用Thread中的start方法,开启线程
        for (int i = 0; i < 10; i++) {
            System.out.println(Thread.currentThread().getName()+"执行了"+i);
        }
    }
}

实现Runnable接口的基础上通过匿名内部类创建多线程

Thread(Runnable target, String name) :name指的是给线程设置名字

public class Test {
    public static void main(String[] args) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 10; i++) {
                    System.out.println(Thread.currentThread().getName()+"执行了"+i);
                }
            }
        },"哈哈").start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 10; i++) {
                    System.out.println(Thread.currentThread().getName()+"执行了"+i);
                }
            }
        },"你好").start();
    }
}

执行结果如下
在这里插入图片描述

继承Thread类和实现Runnable接口两种实现多线程的方式区别

  1. 继承Thread类方式,只支持单继承,有继承的局限性
  2. 实现Runnable接口方式:没有继承的局限性,可以解决需要继承其它类的需求
MyThread extends 其它类 implements Runnable

三、实现Callable接口

Callable是一个接口,类似于Runnable,其中的方法call() 类似于Runnable接口的run()方法是用来设置线程任务的
call()和run()的区别:call()方法有返回值,而且异常可以throws。run()方法没有返回值,而且有异常不可以throws。

获取call()方法的返回值

FutureTask 实现了一个接口:Future
FutureTask中有一个方法get() 用来获取call方法的返回值。

public class MyCallable implements Callable<String> {
    @Override
    public String call() throws Exception {
        for (int i = 0; i < 10; i++) {
            System.out.println(Thread.currentThread().getName()+"执行了"+i);
        }
        return "call方法返回值";
    }
}
public class Test {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        MyCallable myCallable = new MyCallable();
        FutureTask<String> futureTask = new FutureTask<>(myCallable);
        Thread t1 = new Thread(futureTask);//创建Thread对象-> Thread(Runnable target)
        t1.start();
        for (int i = 0; i < 10; i++) {
            System.out.println("main线程执行了"+i);
        }
        System.out.println(futureTask.get());//调用get方法获取call方法返回值
    }
}

运行结果如下:
在这里插入图片描述

四、线程池的方式创建多线程

线程池(ThreadPool)是一种基于池化思想管理和使用线程的机制:它是将多个线程预先存储在一个“池子”内,当有任务出现时可以避免重新创建和销毁线程所带来性能开销,只需要从“池子”内取出相应的线程执行对应的任务即可。解决了之前每来一个线程任务,就需要创建一个线程对象去执行,用完还要销毁线程对象。线程任务多了,就需要频繁创建线程对象和销毁线程对象耗费内存资源多的问题。

  1. 创建获取线程池对象用Executors中的静态方法,其中的参数nThreads指定了线程池中最多创建的线程对象条数。返回值ExecutorService 是线程池,用来管理线程对象。
static ExecutorService newFixedThreadPool(int nThreads)  
  1. ExecutorService中的submit方法用于执行线程任务。返回值用Future接收。

  2. void shutdown() 有序关闭线程池,其中先前提交的任务将被执行,但不会接受任何新任务。

public class MyCallable implements Callable<String> {
    @Override
    public String call() throws Exception {
        return "call方法返回值";
    }
}
public class Test {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        ExecutorService es = Executors.newFixedThreadPool(2);
        Future<String> future = es.submit(new MyCallable());
        System.out.println(future.get());
        es.shutdown(); //有序关闭线程池
    }
}

执行结果如下,如果注释掉了es.shutdown()可以看到程序并没有结束,线程池等的新的线程任务到来。
在这里插入图片描述
具体可以看看这篇文章

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

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

相关文章

【详细教程】PowerDesigner导出表结构word文档

&#x1f4d6;【详细教程】PowerDesigner导出表结构word文档 ✅第一步&#xff1a;新建报告✅第二步&#xff1a;配置导出的参数✅第三步&#xff1a;导出 ✅第一步&#xff1a;新建报告 ✅第二步&#xff1a;配置导出的参数 如果你只需要导出纯粹的表结构&#xff0c;那么下面…

音频demo:使用opencore-amr将PCM数据与AMR-NB数据进行相互编解码

1、README a. 编译 编译demo 由于提供的.a静态库是在x86_64的机器上编译的&#xff0c;所以仅支持该架构的主机上编译运行。 $ make编译opencore-amr 如果想要在其他架构的CPU上编译运行&#xff0c;可以使用以下命令&#xff08;脚本&#xff09;编译opencore-amr[下载地…

Html5前端基本知识整理与回顾上篇

今天我们结合之前上传的知识资源来回顾学习的Html5前端知识&#xff0c;与大家共勉&#xff0c;一起学习。 目录 介绍 了解 注释 标签结构 排版标签 标题标签 ​编辑 段落标签 ​编辑 换⾏标签 ​编辑 ⽔平分割线 ⽂本格式化标签 媒体标签 绝对路径 相对路径 …

【Python】不小心卸载pip后(手动安装pip的两种方式)

文章目录 方法一&#xff1a;使用get-pip.py脚本方法二&#xff1a;使用easy_install注意事项 不小心卸载pip后&#xff1a;手动安装pip的两种方式 在使用Python进行开发时&#xff0c;pip作为Python的包管理工具&#xff0c;是我们安装和管理Python库的重要工具。然而&#x…

接口调用的三种方式

例子&#xff1a; curl --location http://110.0.0.1:1024 \ --header Content-Type: application/json \ --data {"task_id": 1 }方式一&#xff1a;postman可视化图形调用 方式二&#xff1a;Vscode中powershell发送请求 #powershell (psh) Invoke-WebRequest -U…

用R在地图上绘制网络图的三种方法

地理网络图与传统的网络图不同&#xff0c;当引用地理位置进行节点网络可视化时&#xff0c;需要将这些节点放置在地图上&#xff0c;然后绘制他们之间的连结。Markus konrad的帖子(https://datascience.blog.wzb.eu/2018/05/31/three-ways-of-visualizing-a-graph-on-a-map/)&…

Linux系统编程——线程控制

目录 一&#xff0c;关于线程控制 二&#xff0c;线程创建 2.1 pthread_create函数 2.2 ps命令查看线程信息 三&#xff0c;线程等待 3.1 pthread_join函数 3.2 创建多个线程 3.3 pthread_join第二个参数 四&#xff0c;线程终止 4.1 关于线程终止 4.2 pthread_exit…

LeetCode 算法:腐烂的橘子 c++

原题链接&#x1f517;&#xff1a;腐烂的橘子 难度&#xff1a;中等⭐️⭐️ 题目 在给定的 m x n 网格 grid 中&#xff0c;每个单元格可以有以下三个值之一&#xff1a; 值 0 代表空单元格&#xff1b;值 1 代表新鲜橘子&#xff1b;值 2 代表腐烂的橘子。 每分钟&#…

Java版Flink使用指南——定制RabbitMQ数据源的序列化器

大纲 新建工程新增依赖数据对象序列化器接入数据源 测试修改Slot个数打包、提交、运行 工程代码 在《Java版Flink使用指南——从RabbitMQ中队列中接入消息流》一文中&#xff0c;我们从RabbitMQ队列中读取了字符串型数据。如果我们希望读取的数据被自动化转换为一个对象&#x…

JAVA案例ATM系统

一案例要求&#xff1a; 首先完成ATM的用户登录和用户开户两个大功能&#xff0c;用户开户有账户名&#xff0c;性别&#xff0c;账户密码&#xff0c;确认密码&#xff0c;每次取现额度&#xff0c;并且随机生成一个7位数的账号&#xff0c;用户登录功能有查询&#xff0c;存…

k8s 部署 metribeat 实现 kibana 可视化 es 多集群监控指标

文章目录 [toc]环境介绍老(来)板(把)真(展)帅(示)helm 包准备配置监控集群获取集群 uuid生成 api_key配置 values.yaml 配置 es 集群获取集群 uuid 和 api_key配置 values.yaml 查看监控 缺少角色的报错 开始之前&#xff0c;需要准备好以下场景 一套 k8s 环境 k8s 内有两套不同…

Aqara 发布多款智能照明新品,引领空间智能新时代

7月8日&#xff0c;全球 IoT 独角兽品牌 Aqara 以“光&#xff0c;重塑空间想象”为主题&#xff0c;举办了线上智能照明新品沟通会。 会上&#xff0c;Aqara 正式发布一系列引领行业的智能照明新品&#xff0c;包括银河系列轨道灯 V1 以及繁星系列妙控旋钮 V1 等&#xff0c;…

Hospital Management System v4.0 SQL 注入漏洞(CVE-2022-24263)

前言 CVE-2022-24263 是一个影响 Hospital Management System (HMS) v4.0 的 SQL 注入漏洞。这个漏洞允许攻击者通过注入恶意 SQL 代码来获取数据库的敏感信息&#xff0c;甚至可能控制整个数据库。以下是对这个漏洞的详细介绍&#xff1a; 漏洞描述 在 Hospital Management…

使用Keil 点亮LED灯 F103ZET6

1.新建项目 不截图了 2.startup_stm32f10x_hd.s Keil\Packs\Keil\STM32F1xx_DFP\2.2.0\Device\Source\ARM 搜索startup_stm32f10x_hd.s 复制到项目路径&#xff0c;双击Source Group 1 3.项目文件夹新建stm32f10x.h&#xff0c; 新建文件main.c #include "stm32f10x…

OS-HACKNOS-2.1

确定靶机IP地址 扫描靶机开放端口信息 目录扫描 访问后发现个邮箱地址 尝试爆破二级目录 确定为wordpress站 利用wpscan进行漏洞扫描 #扫描所有插件 wpscan --url http://192.168.0.2/tsweb -e ap 发现存在漏洞插件 cat /usr/share/exploitdb/exploits/php/webapps/46537.txt…

Camera Raw:裁剪

Camera Raw 的裁剪 Crop面板提供了裁剪、旋转、翻转、拉直照片等功能&#xff0c;通过它们可以更精确地调整照片的视角和范围&#xff0c;以达到最佳二次构图的视觉效果。 快捷键&#xff1a;C ◆ ◆ ◆ 使用方法与技巧 1、使用预设 选择多种裁剪预设&#xff08;如 1:1、16:…

前端传到后端的data数组中有些属性值为空

将前端输入框中的值全部放入data中传入后端&#xff0c;但是在后端查看发现后端接收到的数据有些属性值为空。 第一种情况&#xff1a;只有第一个属性为空&#xff0c;其余属性接收正常 可能原因&#xff1a;后端用来接收的 比如前端发送数据&#xff1a; 实际上前端发送的数…

防火墙详解(USG6000V)

0、防火墙组网模式 防火墙能够工作在三种模式下分别是路由模式、透明模式、旁路检测模式、混合模式 0.1、路由模式 路由模式&#xff1a;防火墙全部以第三层对外连接&#xff0c;即接口具有IP 地址。一般都用在防火墙是边界的场景下 防火墙需要的部署/配置&#xff1a; 接…

【Excel】 批量跳转图片

目录标题 1. CtrlA全选图片 → 右键 → 大小和属性2. 取消 锁定纵横比 → 跳转高度宽度 → 关闭窗口3. 最后一图拉到最后一单元格 → Alt吸附边框![](https://i-blog.csdnimg.cn/direct/d56ac1f41af54d54bb8c68339b558dd1.png)4. CtrlA全选图片 → 对齐 → 左对齐 → 纵向分布!…