java如何创建线程

article/2025/11/8 2:11:35

java如何创建线程

  • 1. java如何创建线程
    • 1.1 通过继承Thread类来创建线程
    • 1.2 通过实现Runnable接口来创建线程
    • 1.3 通过匿名内部类来创建线程
    • 1.4 lambda表达式
    • 1.5 通过实现Runnable接口的方式创建线程目标类的优缺点

1. java如何创建线程

一个线程在Java中使用一个Thread实例来描述。Thread类是Java语言的一个重要的基础类,位于java.lang包中。Thread类有不少非常重要的属性方法用于存储和操作线程的描述信息.

Thread类的构造方法:

在这里插入图片描述

1.1 通过继承Thread类来创建线程

666
666
666
666
(1) 继承Thread类,创建一个新的线程类。

(2) 同时重写run()方法,将需要并发执行的业务代码编写在run()方法中。

代码写法如下:

class MyThread extends Thread {
//注释这个方法重写了父类方法@Overridepublic void run() {//需要并发执行的代码System.out.println("hello t");}
}
public class ThreadDemo1 {//第一种写法是使用Thread的run描述线程入口public static void main(String[] args) {Thread t = new MyThread();//向上转型t.start();//会创建新的线程System.out.println("hello main");}
}

此时我们可以运行一下:

在这里插入图片描述
此时呢~
我们就通过start()创建了一个新的线程,并且由于我们调用了start(),所以系统自动帮我们调用了run(),此时的run()是执行在 t 线程里面的.

我们可以通过打开jconsole.exe 这个文件来查看我们java在执行期间运行的线程.

由于线程执行完就会结束,为了方便查看,我们写一个死循环来方便我们观看.

在这里插入图片描述

在这里插入图片描述
此时,红色框框里面的main线程就是我们的主线程,另一个Thread-0就是我们刚才创建的一个 t 线程,由于我们没有指定名字,所以这个线程名字默认从0往后递增~

在这里插入图片描述
红色框框里面的两个构造方法是可以修改这个线程的名字的,先讲第一个红色框框里面的.

我们先在MyThread这个类中,通过快速创建构造方法,将可以传入名字参数的构造方法写出来.
在这里插入图片描述

class MyThread extends Thread {//调用父类的构造方法public MyThread(String name) {super(name);}@Overridepublic void run() {while (true){try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("hello t");}}
}

此时呢?我们就可以对这个线程起名字了.

在这里插入图片描述

1.2 通过实现Runnable接口来创建线程

写一个类MyRunnable实现Runnable接口,覆写run()方法,创建MyRunnable对象runnable,将runnable作为参数调用Thread有参构造,创建线程thread,调用start()启动线程。

我们先查看一下Runnable这个接口.


Runnable有且仅有一个抽象方法 —— void run(),代表被执行的用户业务逻辑的抽象,在使用的时候,将用户业务逻辑编写在Runnable实现类的run()方法中。当Runnable实例传入Thread实例的target属性后,Runnable接口的run()的方法将被异步调用。

如何理解上面这句话呢?

我们先理解第一句话: 将用户业务逻辑编写在Runnable实现类的run()方法中.

在这里插入图片描述

由于我们的MyThread这个类实现了Runnable这个接口,所以我们需要重写这个接口里面的run()方法.如上图.

我们再来理解第二句话: 当Runnable实例传入Thread实例的target属性后,Runnable接口的run()的方法将被异步调用。

首先呢?我们需要new一个Runnable的实例.

 MyRunnable myRunnable = new MyRunnable();

接着又讲到将Runnable的实例传入到Thread实例的target属性.

target是什么?

在Thread类的run()方法中,如果target(执行目标)不为空,就执行target属性的run()方法。而target属性是Thread类的一个实例属性,并且target属性的类型为Runnable

在这里插入图片描述

此时我们的MyRunable的类型就是target的类型(Runnable),所以此时我们实例的 myrunable 就可以作为参数传入到Thread的构造方法中.


class MyRunnable implements Runnable {@Overridepublic void run() {while (true){try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("hello t");}}
}
public class ThreadDemo2 {//第二种方法是使用Runnable interface(接口) 来描述线程入口public static void main(String[] args) {//先实例化一个实现Runnable接口的类MyRunnable myRunnable = new MyRunnable();//将这个类的引用作为参数传入Thread的构造方法中Thread t = new Thread(myRunnable);//此时可以通过start()创建一个线程,在这个线程中调用这个MyRunnable这个类中的run()方法.t.start();while (true) {try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("hello main");}}
}

当我们运行时:

在这里插入图片描述

当然,我们也可以自己指定线程名字,这里就不进行演示了.

1.3 通过匿名内部类来创建线程

因为有些线程是只需要调用一次的,所以我们可以通过匿名内部类这样的方式来进行run()的重写.

代码如下:

在这里插入图片描述

在实例化这个对象时,在其后面写入一个{},此时就可以在这个{}中写入自己需要的方法.

注意:此时这个类是一次性的类.

上述代码的运行结果是:

在这里插入图片描述
可能有人就会问了,你这次怎么没有main线程啊,其实是因为main线程在执行完t.start()之后后续就没有代码需要执行了,所以自然这个线程就结束了,于是就是我们上述看到的,只有 t 线程.

在实现Runnable编写target执行目标类时,如果target实现类是一次性类,可以使用匿名实例的形式。

public class ThreadDemo4 {public static void main(String[] args) {Thread t = new Thread(new Runnable() {@Overridepublic void run() {while (true) {System.out.println("hello t");try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}}});t.start();while (true) {try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("hello main");}}
}

1.4 lambda表达式

使用Lambda表达式优雅地创建Runnable线程目标类
在这里插入图片描述
我们通过观察这个Runnable接口可以发现,上面有一串注释,@FunctionalInterface 这个注释的意思就是标记这个接口为函数式接口,在Java中,“函数式接口”是有且仅有一个抽象方法的接口。反过来说,如果一个接口中包含两个或两个以上的抽象方法,就不能使用@FunctionalInterface注解,否则编译会报错。

Runnable接口是一个函数式接口,在接口实现时可以使用Lambda表达式提供匿名实现,编写出比较优雅的代码。 如果一个接口中有多个抽象方法,那样没有办法使用Lambda表达式简化。

  public static void main(String[] args) {//()里面放参数,{}里面放函数体Thread t = new Thread(()->{while (true) {try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("hello t");}},"猪猪侠");t.start();while (true) {try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("hello main");}}

但是呢? 此时小鱼有一个问题问大家,大家对比五段代码,找到哪几个有错误并且说明错误原因.


public class ThreadDemo5 {
//例一static int count = 0;public static void main(String[] args) {Thread t = new Thread(()->{while (true){System.out.println(count);try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}});t.start();}
}
public class ThreadDemo5 {//例二public static void main(String[] args) {int count = 0 ;Thread t = new Thread(()->{while (true){System.out.println(count);try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}});count = 5;t.start();}
}
public class ThreadDemo5 {//例三public static void main(String[] args) {int count = 0 ;Thread t = new Thread(()->{while (true){System.out.println(count);try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}});t.start();}
}
public class ThreadDemo5 {//例四public static void main(String[] args) {final int count = 0 ;Thread t = new Thread(()->{while (true){System.out.println(count);try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}});t.start();}
}
public class ThreadDemo5 {//例五public static void main(String[] args) {int count = 0 ;Thread t = new Thread(()->{while (true){System.out.println(count++);try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}});t.start();}
}

(1) 第一个没有错误,由于count是成员变量,在线程中是共享资源,所以lambda表达式中是可以访问这个变量并且对其进行修改的.
(2) 第二个有错误,Lambda 表达式(匿名类) 不能访问非 final 的局部变量 .

因为成员变量存在堆中,而局部变量是在栈上分配,存在于虚拟机栈的局部变量表中,Lambda 表达(匿名类) 有可能会在另一个线程中执行。如果在线程中要直接访问一个局部变量,可能线程执行时该局部变量已经被销毁了,而 final 类型的局部变量在 Lambda 表达式(匿名类) 中其实是局部变量的一个拷贝

(3) 第三个没有错误,虽然我们的count是局部变量,但是由于我们的代码并未有对该变量进行后续的修改,我们可以称这个count变量为实际final,意思就是虽然没有被final修饰,但是由于并没有修改这个变量的值,所以在lambda表达式中可以使用.
(4) 没有问题

(5) 错误,lambda表达式不能修改局部变量.原因如下:

lambda表达式不能修改局部变量

1.5 通过实现Runnable接口的方式创建线程目标类的优缺点

通过实现Runnable接口的方式创建线程目标类有以下缺点:

  • 所创建的类并不是线程类,而是线程的target执行目标类,需要将其实例作为参数传入线程类的构造器,才能创建真正的线程。
  • 如果访问当前线程的属性,不能直接访问Thread的实例方法,必须通过Thread.currentThread()获取当前线程实例,才能访问和控制当前线程。

通过实现Runnable接口的方式创建线程目标类有以下优点:

  • 可以避免由于Java单继承带来的局限性。如果异步逻辑所在类已经继承了一个基类,就没有办法再继承Thread类。比如,当一个Cat类继承了Animal类,再要继承Thread类就不行了。所以在已经存在继承关系的情况下,只能使用实现Runnable接口的方式。
  • 逻辑和数据更好分离。通过实现Runnable接口的方法创建多线程更加适合同一个资源被多段业务逻辑并行处理的场景。在同一个资源被多个线程逻辑异步、并行处理的场景中,通过实现Runnable接口的方式设计多个target执行目标类可以更加方便、清晰地将执行逻辑和数据存储分离,更好地体现了面向对象的设计思想。

http://chatgpt.dhexx.cn/article/k15pLepX.shtml

相关文章

Java多线程 - Java创建线程的4种方式

文章目录 1. Java创建线程有哪几种方式?1.1 线程创建方法一:继承Thread类创建线程类1.2 线程创建方法二:实现Runnable接口创建线程目标类1.5 线程创建方法三:使用Callable和FutureTask创建线程1.6 线程创建方法四:通过…

java创建线程的四种方式

1&#xff09;继承Thread类创建线程 如图所示: //继承Thread类 class Aclass extends Thread{//输出100以内的偶数Overridepublic void run() {for (int i 1; i <100; i) {System.out.println(getName()":"i);}} } 测试: Thread t1 new Aclass();t1.setName…

Java创建线程的七种方法,全网最全面总结~

目录 前言 一、继承Thread&#xff0c;重写run方法 二、实现Runnable接口&#xff0c;重写run方法 三、使用匿名内部类创建 Thread 子类对象 四、使用匿名内部类&#xff0c;实现Runnable接口 五、lambda表达式 六、实现Callable接口 七、使用线程池创建线程 前言 属于基…

java创建线程(Thread)的5种方式

java创建线程&#xff08;Thread&#xff09;的5种方式 方式一&#xff1a;继承于Thread类方式二&#xff1a;实现Runnable接口方式三&#xff1a;实现Callable接口方式四&#xff1a;使用线程池方式五&#xff1a;使用匿名类 方式一&#xff1a;继承于Thread类 步骤&#xff1…

前端开发与vscode开发工具介绍

文章目录 1、前端开发2、vscode安装和使用2.1、下载地址2.2、插件安装2.3、设置字体大小2.4、开启完整的Emmet语法支持2.5、创建项目2.6、保存工作区2.7、新建文件夹和网页 1、前端开发 前端工程师“Front-End-Developer”源自于美国。大约从2005年开始正式的前端工程师角色被…

IntelliJ IDE 插件开发指南

作者介绍 洪进锋&#xff0c;字节跳动后端研发工程师&#xff0c;参与过高并发系统&#xff08;百万QPS&#xff09;设计与研发工作。在开源项目方面混过 Sharding-JDBC 的 PR。个人开发的 IntelliJ IDE 插件 Redis Manager&#xff0c;目前在官方插件库中下载量 30K&#xff0…

真的要转到云IDE了吗?VS Code的开源IDE

云IDE产品介绍 云IDE使用教程 免费使用地址&#xff1a;点击【云IDE】&#xff0c;即可开始创建工作空间啦~ 前言 CSDN最新产品【云IDE】来啦&#xff01;【云IDE】将为各位技术er一键秒级构建云开发环境&#xff0c;提升开发效率&#xff01; 1. 什么是IDE&#xff1f; 做…

编辑器和IDE到底有什么区别呢?

其实很多接触了开发的工作人员都会接触以上 两种工具&#xff0c;编辑器&#xff0c;IDE。 其实我最刚开始的时候真的分不清&#xff0c;感觉都是开发的&#xff0c;上班以后呢慢慢就发现了两者的不同。 刚刚看知乎&#xff0c;发现一位哥们说话挺有意思的&#xff0c;比喻也…

初识Node.js之IDE的选择

其实就如同Java一样&#xff0c;Node可以选择的IDE不止一种&#xff0c;常见的比如webstorm&#xff0c;Visual Studio Code&#xff0c;其实都可以应付日常的工作需求&#xff0c;今天我要介绍的IDE&#xff0c;其实就是Visual Studio Code(接下来简称vs code)。怎么评价vs co…

【编辑器】VSCode的Web前端(html,css,JavaScript)开发环境打造

1、安装VScode和浏览器 VScode安装&#xff1a;https://code.visualstudio.com/ Chrome安装&#xff1a;https://www.google.com/intl/zh-CN/chrome/ node.js 安装&#xff1a;https://nodejs.org/zh-cn/download/ Web前端开发主要包括html&#xff0c;css&#xff0c;JavaScr…

IDE集成开发工具-IDEA(一)之IDE的概念

IDE的概念 集成开发环境&#xff08;IDE&#xff0c;Integrated Development Environment &#xff09;是用于提供程序开发环境的应用程序&#xff0c;一般包括代码编辑器、编译器、调试器和图形用户界面等工具。集成了代码编写功能、分析功能、编译功能、调试功能等一体化的开…

11个裸VSCode必备插件,助你打造一个前端开发IDE

VSCode 轻量、开源&#xff0c;新鲜下载的 VSCode 可谓是身无长物、一穷二白&#xff0c;连个项目管理的功能都没有。 身轻如燕的 VSCode 对于后端开发说可能有点幼稚&#xff0c;但对于前端来说刚刚好&#xff0c;毕竟不需要搞什么 Docker、数据库等等&#xff0c;装俩 VSCod…

「干货」前端开发者最常用的六款IDE

微信公众号&#xff1a;javafirst 一、Visual Studio Code 下载地址&#xff1a;https://code.visualstudio.com/ 功能介绍&#xff1a; 微软在2015年4月30日Build 开发者大会上正式宣布了 Visual Studio Code 项目&#xff1a;一个运行于 Mac OS X、Windows和 Linux 之上的…

IDEA使用前端基础

常用快捷键和快捷语句 CtrlShiftEnter&#xff1a;将输入的if、for、函数等等补上{}或者;使代码语句完整 CtrlAltT&#xff1a;将选中的代码使用if、while、try/catch等包装 Alt/&#xff1a;自动完成 AltEnter&#xff1a;自动提示完成 Ctrl/&#xff1a;使用//进行注释 Ctrl…

IDE的详细介绍

IDE&#xff08;集成开发环境&#xff09; 就是电脑上编程时用的应用&#xff0c;比如&#xff1a;visual studio&#xff08;如图&#xff09;&#xff0c; eclipse等。IDE一般包括&#xff1a;代码编辑器、编译器、调试器和图形用户界面等工具。IDE是集成了代码编写功能、分…

IDE等开发工具的使用(VSCODE + IDEA)

Mac下各按键对应含义 ⌥ ⌃⇧⌘→ / ← ↑ / ↓ 各种快捷键的组合场景 左ctrl 待定 左alt cmd 待定 左ctrl shift 待定 左ctrl cmd 待定 左shift cmd 待定 1.熟悉的Mac下的快捷键&#xff08;持续补充&#xff09; 附&#xff1a;Vscode KeyShortCut 功能 快捷键 功能…

【HBuilder】前端IDE神器

Hbulider目录 一、Hbulider简介1.1 Hbulider出身1.2 Hbulider特点 二、Hbulider安装2.1 Hbulider官网下载2.2 解压&#xff0c;发送快捷方式到桌面 三、Hbulider启动3.1 选择主题和快捷键方案 四、Hbulider使用4.1 失去焦点自动保存 一、Hbulider简介 1.1 Hbulider出身 HBuild…

前端vscode必备插件(强烈推荐)

目录 一、前言 二、工具推荐 1.《Chinese (Simplified) (简体中文) Language》 2.《ESLint》 3.《Git History》 4.vscode-icons 5.Path Intellisense 6.《Vetur》 7.《GitLens — Git supercharged》 8.《Image preview》 9.Debugger for Chrome 10.Prettier 11…

前端开发IDE---VSCode前端开发环境配置

所安装的插件如下&#xff1a; 1、open in browser(2.0.0版本&#xff09;详细内容见VSCode插件搜索。 修改默认浏览器的步骤&#xff1a; File>preferences>settings>点击那三个点>选择open settings.json>找到plugin open-in-browser按照提示在右边的json文…

前端开发IDE WebStorm使用

一、安装WebStorm 前往官网下载WebStorm: The Smartest JavaScript IDE, by JetBrains 二、无限试用期工具 链接&#xff1a;百度网盘 请输入提取码 提取码&#xff1a;ide0 直接将压缩包拖入IDE窗口&#xff0c;将会自动刷新一次试用期时间。 也可以手动刷新&#xf…