Java中几种常见的创建线程的方式

创建线程的几种方式

方法解释
Thread()创建线程对象
Thread(String name)创建线程对象,并给线程命名,不会影响线程
Thread(Runnable runnable)使用Runnable对象创建线程
Thread(Runnable runnable, String name)使用Runnable对象创建线程并给线程命名

方式1.创建一个类,继承Thread

每一个线程都是一个单独的”执行流“, 都可以执行一段代码逻辑,但是,线程是从哪里开始执行呢???就需要提供一个入口,而run方法就是线程的入口,表示就从run方法这里开始执行;

此时,我们写的一个Java程序其实就是一个进程,一个进程里面至少要有一个线程,就是主线程,而在Java程序中,主线程的入口方法就是main方法;

//创建一个类,继承Thread
class MyThread extends Thread{//重写Thread里面的run方法,这个方法就是线程的入口@Overridepublic void run() {//代码逻辑}
}
public class Demo1 {public static void main(String[] args) {}
}

但是,只有run方法还是不够的,run方法只是线程执行的入口,只是说明了线程从哪个地方开始执行,run方法里面只是定义了线程要做哪些任务,需要在主线程中,调用 start() 方法来创建一个新的线程,线程创建后,线程就会调用run()方法开始执行任务。

代码如下:

//创建一个类,继承Thread
class MyThread extends Thread{//重写Thread里面的run方法,这个方法就是线程的入口@Overridepublic void run() {System.out.println("线程正在工作");}
}
public class Demo1 {public static void main(String[] args) {MyThread thread = new MyThread();thread.start();//run() 和 start() 都是Thread的方法//run()方法只是线程的入口//start()方法才是调用了系统API来创建一个线程,让线程再调用run来执行任务}
}

在这里插入图片描述

下面演示一下两个线程并发执行的情况:

class MyThread extends Thread{//重写Thread里面的run方法,这个方法就是线程的入口@Overridepublic void run() {//写一个while循环让这个线程一直打印while(true) {System.out.println("hello Thread");try {//进行一个休眠方便观察Thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}}}
}
public class Demo1 {public static void main(String[] args) throws InterruptedException {MyThread thread = new MyThread();thread.start();//写一个while循环,一直打印while(true) {System.out.println("hello main");//进行一个休眠方便观察Thread.sleep(1000);}}
}

在这里插入图片描述

上述结果就可以看到,两个线程分别在执行自己的代码,这也就印证了每一个线程都是一个单独的”执行流“, 本来在运行时只有一个执行流,但是遇见 thread.start() ,就开始了兵分两路”同时执行“, 就达到了并发编程的效果,而这里的并发指的是”并行+并发“, 因为,程序员在写代码的时候,是无法感知到这两个线程到底是在一个CPU核心上调度执行还是在两个CPU核心上同时执行, 所以在宏观上也就是我们人的肉眼看着都是在同时执行的,这一点在进程那篇文章中已经讲解的很清楚了。

如果将代码中的 thread.start() 改为 thread.run() 会发生什么呢?

在这里插入图片描述

如果改成thread.run(), 它就只剩下一个主线程了,只会按照代码的顺序依次执行,就变成了单独的方法调用,这就不是多线程了,只有当run()方法结束后,才会继续向下执行;也就没有实现”并发编程”;

在这里插入图片描述

方式2.创建一个类,实现Runnable接口

使用Runnable接口和继承Thread的区别就是为了解耦合,Runnable 就相当于是一个任务,在Runnable 中,也实现了 run() 方法,所以,就可以在Runnable 中写逻辑代码,然后,将这个Runnable 任务交给线程来执行。

代码如下:

//创建一个类,实现Runnable接口
class MyThread2 implements Runnable{@Overridepublic void run() {while(true) {System.out.println("hello Thread");}}
}
public class Demo2 {public static void main(String[] args) {//Runnable 就表示的是这是一个可执行的任务Runnable runnable = new MyThread();Thread thread = new Thread(runnable);thread.start();while(true) {System.out.println("hello main");}}
}

方式3.继承Thread,重写run(), 但是使用匿名内部类

public static void main(String[] args) {Thread thread = new Thread() {@Overridepublic void run() {System.out.println("hello Thread");}};thread.start();System.out.println("hello main");}

方法4.实现Runnable,重写run(), 但是使用匿名内部类

    public static void main(String[] args) {Runnable runnable = new Runnable() {@Overridepublic void run() {System.out.println("hello Thread");}};Thread thread = new Thread(runnable);thread.start();System.out.println("hello main");}

方式5.使用Lambda表达式

    public static void main(String[] args) {Thread thread = new Thread(() -> {System.out.println("hello Thread");});thread.start();System.out.println("hello main");}

注意:上述这几种创建线程的方式只是一部分并非全部,创建线程有许多种方式,这几种比较简单而已,在多线程进阶中,还会再介绍几种创建线程的方式。

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

AI论文速读 | 立场观点:时间序列分析,大模型能告诉我们什么?

题目:Position Paper: What Can Large Language Models Tell Us about Time Series Analysis 作者:Ming Jin ; Yifan Zhang ; Wei Chen ; Kexin Zhang ; Yuxuan Liang ; Bin Yang ; Jindong Wang ; Shirui Pan ; Qingsong Wen 机构:莫纳什大…

【C++】STL容器之string(修改操作)

💐 🌸 🌷 🍀 🌹 🌻 🌺 🍁 🍃 🍂 🌿 🍄🍝 🍛 🍤 📃个人主页 :阿然成长日记 …

MYSQL学习笔记:索引

MYSQL学习笔记:索引 文章目录 MYSQL学习笔记:索引索引的分类索引的创建删除索引优化B树索引B树InnoDB主键和二级索引树聚集索引与非聚集索引哈希索引INNODB的自适应哈希索引索引和慢查询 用索引也是要涉及磁盘I/O的操作的索引也是一种数据结构&#xff0…

连续小波变换

1 连续小波变换 连续小波变换(CWT)用于分解小波信号。小波是时间上小的、高度局部的振荡。傅里叶变换将信号分解为无限长的正弦和余弦,从而丢失了所有时间位置信息,而CWT 的基本功能是时间局部化父小波的缩放和移位版本。CWT 用于构建信号的时频表示&am…

LeetCode225. 用队列实现栈(C++)

LeetCode225. 用队列实现栈 题目链接代码 题目链接 https://leetcode.cn/problems/implement-stack-using-queues/description/ 代码 class MyStack { public:queue<int> q1;queue<int> q2;MyStack() {}void push(int x) {q1.push(x);}int pop() {int size q1…

45、WEB攻防——通用漏洞PHP反序列化POP链构造魔术方法原生类

文章目录 序列化&#xff1a;将java、php等代码中的对象转化为数组或字符串等格式。代表函数serialize()&#xff0c;将一个对象转换成一个字符&#xff1b;反序列化&#xff1a;将数组或字符串等格式还成对象。代表函数unserialize()&#xff0c;将字符串还原成一个对象。 P…

配置前端项目到 github-pages

Quickstart for GitHub Pages - GitHub Docs

MySQL:合并查询语句

1、查询表的数据 t_book表数据 SELECT * FROM db_book.t_book; t_booktype表数据 SELECT * FROM db_book.t_booktype; 提醒&#xff1a; 下面的查询操作的数据来自上图查询表的数据 2. 使用 UNION 查询结果合并&#xff0c;会去掉重复的数据 使用UNION关键字是&#xff0c;数…

刷题日记 | 字符串扩容和增强型for循环

for(char c:s)遍历字符串 增强型for循环 C for(char c:s)遍历字符串 增强型for循环_c for (char c : s)-CSDN博客 字符串使用前要进行扩容 reserve函数 【CString类成员函数辨析】resize(),size(),capacity(),reserve()函数的解析与对比_c reserve函数-CSDN博客 a.size() 用来…

kali安装ARL灯塔(docker)

1、root身份进入容器 ┌──(root㉿Kali)-[~/桌面] └─# su root ┌──(root㉿Kali)-[~/桌面] └─# docker 2、先更新再克隆 ┌──(root㉿Kali)-[~/桌面] └─# apt-get update …

论文笔记:基于互信息估计和最大化的深度表示学习

整理了ICLR2019 LEARNING DEEP REPRESENTATIONS BY MUTUAL INFORMATION ESTIMATION AND MAXIMIZATION&#xff09;论文的阅读笔记 背景模型 论文地址&#xff1a;DIM code&#xff1a;代码地址 背景 发现有用的表示是深度学习的一个核心目标&#xff0c;由于之前的工作已经可以…

苍穹外卖知识点总结(一)

简介 技术选型 展示项目中使用到的技术框架和中间件。 用户层&#xff1a;node.js Vue.js ElementUI 微信小程序 apache echarts 网关层&#xff1a;nginx 应用层&#xff1a;Spring Boot Spring MVC Spring Task httpclie…