Java多线程——2.创建新线程
Java多线程
线程的基本概念
当一个Java程序启动时,实际上是启动了一个JVM进程,JVM会创建一个主线程来执行main()方法。除此之外,我们还可以创建多个额外的线程,这些线程可以并发执行不同的任务,从而充分利用多核CPU的计算能力。
- 进程:一个正在运行的程序,拥有独立的内存空间和系统资源
- 线程:进程内部的执行单元,共享进程的资源,拥有独立的执行路径
- 多线程:一个进程中同时运行多个线程,实现并发执行
创建新线程的两种方式
Java提供了两种主要方式来创建新线程,各有其适用场景和特点。
方式一:继承Thread类并覆写run()方法
Thread类是Java中线程操作的核心类,通过继承该类并覆写其run()方法,可以定义线程要执行的任务:
// 自定义线程类
class MyThread extends Thread {
@Override
public void run() {
// 线程要执行的任务代码
System.out.println("新线程执行中...");
for (int i = 0; i < 5; i++) {
System.out.println("子线程: " + i);
try {
// 让线程暂停500毫秒
Thread.sleep(500);
} catch (InterruptedException e) {
// 处理中断异常
e.printStackTrace();
}
}
System.out.println("新线程执行完毕");
}
}
// 测试类
public class ThreadExample {
public static void main(String[] args) {
System.out.println("主线程启动");
// 创建线程实例
MyThread thread = new MyThread();
// 启动线程
thread.start();
System.out.println("主线程继续执行");
for (int i = 0; i < 3; i++) {
System.out.println("主线程: " + i);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("主线程执行完毕");
}
}
执行流程解析:
- 主线程创建
MyThread实例 - 调用
start()方法启动新线程,JVM会创建一个新的执行线程 - 新线程执行
run()方法中的代码 - 主线程和新线程并发执行
方式二:实现Runnable接口并覆写run()方法
Runnable接口定义了一个单一的run()方法,通过实现该接口并将实例传递给Thread类,可以更灵活地创建线程:
// 实现Runnable接口
class MyRunnable implements Runnable {
@Override
public void run() {
// 线程要执行的任务代码
System.out.println("新线程执行中...");
// 任务逻辑...
}
}
// 测试类
public class RunnableExample {
public static void main(String[] args) {
System.out.println("主线程启动");
// 创建Runnable实例
MyRunnable runnable = new MyRunnable();
// 将Runnable实例传递给Thread
Thread thread = new Thread(runnable);
// 启动线程
thread.start();
System.out.println("主线程继续执行");
// 主线程逻辑...
}
}
使用Lambda表达式简化(Java 8+):
public class LambdaThreadExample {
public static void main(String[] args) {
System.out.println("主线程启动");
// 使用Lambda表达式创建线程
Thread thread = new Thread(() -> {
System.out.println("新线程执行中...");
// 任务逻辑...
});
thread.start();
System.out.println("主线程继续执行");
// 主线程逻辑...
}
}
两种方式的对比
| 方式 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| 继承Thread | 代码简单,直接使用this指代当前线程 | 无法继承其他类(Java单继承) | 简单的线程任务 |
| 实现Runnable | 可继承其他类,适合多个线程共享资源 | 代码稍复杂,需通过Thread.currentThread()获取当前线程 | 复杂任务,资源共享场景 |
推荐实践:优先使用实现Runnable接口的方式,因为它更灵活,也符合面向接口编程的思想。
线程的启动与执行
创建线程实例后,必须调用start()方法才能真正启动一个新线程。需要特别注意的是,直接调用run()方法并不会创建新线程,而只是在当前线程中执行run()方法中的代码:
public class ThreadStartExample {
public static void main(String[] args) {
Thread thread = new Thread(() -> {
System.out.println("线程执行中,当前线程名: " + Thread.currentThread().getName());
});
// 正确启动新线程
thread.start(); // 输出: 线程执行中,当前线程名: Thread-0
// 错误方式,不会创建新线程
thread.run(); // 输出: 线程执行中,当前线程名: main
}
}
start()方法的工作原理:
- 向JVM请求创建一个新线程
- JVM分配线程所需的资源
- 新线程开始执行
run()方法中的代码 start()方法立即返回,不等待run()方法执行完毕
一个线程对象只能调用一次start()方法,多次调用会抛出IllegalThreadStateException异常。
线程调度与优先级
线程的调度由操作系统和JVM共同负责,程序员无法精确控制线程的执行顺序,但可以通过设置线程优先级来影响调度器的决策。
线程优先级
Java中线程优先级分为1到10共10个级别,默认优先级为5:
public class ThreadPriorityExample {
public static void main(String[] args) {
Thread t1 = new Thread(() -> {
for (int i = 0; i < 1000; i++) {
System.out.println("线程1: " + i);
}
});
Thread t2 = new Thread(() -> {
for (int i = 0; i < 1000; i++) {
System.out.println("线程2: " + i);
}
});
// 设置优先级
t1.setPriority(Thread.MIN_PRIORITY); // 优先级1
t2.setPriority(Thread.MAX_PRIORITY); // 优先级10
t1.start();
t2.start();
}
}
注意事项:
- 优先级高的线程获得的CPU时间片通常更多,但不保证一定先执行
- 不同操作系统对优先级的支持不同,不能过度依赖优先级来控制执行顺序
- 优先级设置应合理,避免设置过多不同优先级的线程
线程休眠
使用Thread.sleep(long millis)方法可以让当前线程暂停执行指定的毫秒数:
public class ThreadSleepExample {
public static void main(String[] args) {
Thread thread = new Thread(() -> {
try {
System.out.println("线程开始执行");
Thread.sleep(2000); // 休眠2秒
System.out.println("线程休眠结束");
} catch (InterruptedException e) {
System.out.println("线程被中断");
return;
}
System.out.println("线程执行完毕");
});
thread.start();
}
}
sleep()方法会抛出InterruptedException,当线程在休眠期间被中断时会触发该异常。
线程的生命周期
一个线程从创建到结束,会经历以下状态:
- 新建状态(New):线程对象创建但未调用
start()方法 - 就绪状态(Runnable):调用
start()方法后,等待CPU调度 - 运行状态(Running):获得CPU时间片,执行
run()方法 - 阻塞状态(Blocked):因某种原因暂停执行(如等待锁、I/O操作)
- 死亡状态(Terminated):
run()方法执行完毕或因异常终止
理解线程的生命周期有助于更好地调试多线程程序,避免出现线程泄漏或死锁等问题。
总结
- 创建线程有两种方式:继承
Thread类或实现Runnable接口 - 必须调用
start()方法才能启动新线程,直接调用run()方法无效 - 线程调度由操作系统控制,优先级可以影响但不能决定执行顺序
Thread.sleep()方法可以暂停线程执行,让出CPU时间片- 一个线程对象只能启动一次,多次启动会抛出异常
- 理解线程的生命周期
Java多线程——2.创建新线程的更多相关文章
- 廖雪峰Java11多线程编程-1线程的概念-2创建新线程
Java语言内置多线程支持: 一个Java程序实际上是一个JVM进程 JVM用一个主线程来执行main()方法 在main()方法中又可以启动多个线程 1.创建新线程 1.1 方法一:使用Thread ...
- Java多线程——<三>简单的线程执行:Executor
一.概述 按照<Java多线程——<一><二>>中所讲,我们要使用线程,目前都是显示的声明Thread,并调用其start()方法.多线程并行,明显我们需要声明多个 ...
- Java多线程(一) —— 线程的状态详解
一.多线程概述 1. 进程 是一个正在执行的程序.是程序在计算机上的一次运行活动. 每一个进程执行都有一个执行顺序.该顺序是一个执行路径,或者叫一个控制单元. 系统以进程为基本单位进行系统资源的调度 ...
- java多线程(四)-自定义线程池
当我们使用 线程池的时候,可以使用 newCachedThreadPool()或者 newFixedThreadPool(int)等方法,其实我们深入到这些方法里面,就可以看到它们的是实现方式是这样的 ...
- java多线程系列六、线程池
一. 线程池简介 1. 线程池的概念: 线程池就是首先创建一些线程,它们的集合称为线程池. 2. 使用线程池的好处 a) 降低资源的消耗.使用线程池不用频繁的创建线程和销毁线程 b) 提高响应速度,任 ...
- Java多线程(1) 创建
一.线程的生命周期及五种基本状态 关于Java中线程的生命周期,首先看一下以下这张较为经典的图: Java线程具有五中基本状态 新建状态(New):当线程对象对创建后,即进入了新建状态,如:Threa ...
- Java多线程(二) —— 线程安全、线程同步、线程间通信(含面试题集)
一.线程安全 多个线程在执行同一段代码的时候,每次的执行结果和单线程执行的结果都是一样的,不存在执行结果的二义性,就可以称作是线程安全的. 讲到线程安全问题,其实是指多线程环境下对共享资源的访问可能会 ...
- Java多线程(五)线程的生命周期
点我跳过黑哥的卑鄙广告行为,进入正文. Java多线程系列更新中~ 正式篇: Java多线程(一) 什么是线程 Java多线程(二)关于多线程的CPU密集型和IO密集型这件事 Java多线程(三)如何 ...
- Java多线程-同步:synchronized 和线程通信:生产者消费者模式
大家伙周末愉快,小乐又来给大家献上技术大餐.上次是说到了Java多线程的创建和状态|乐字节,接下来,我们再来接着说Java多线程-同步:synchronized 和线程通信:生产者消费者模式. 一.同 ...
- Java多线程的创建方法
Java 线程类也是一个 object 类,它的实例都继承自java.lang.Thread 或其子类. 可以用如下方式用 java 中创建一个线程,执行该线程可以调用该线程的 start()方法: ...
随机推荐
- 2024杭电钉耙2-1003 HDOJ7447 绝对不模拟的简单魔方
欢迎您来我的网站看这篇题解! Problem 有一个魔方可能被拧了不超过三次,同时还弄丢了一个角块上的两个贴纸.现在把这两个贴纸贴回去,请问有没有贴错? 只可能拧侧面,不会拧中间层,且每次只能拧 \( ...
- NOIp2020复赛后的故事
NOIp2020复赛后的故事 过渡 \(15\)号,学校开了一个竞赛生大会. 胡校长大致就是说了些鼓励我们的话,让我们放心大胆的去拼搏,别怕因为停课而落下了\(whk\). \(18\sim19\)号 ...
- idea类和方法的注释模板设置
作者:故事我忘了¢个人微信公众号:程序猿的月光宝盒 目录 1.在idea中设置类模板 2.设置方法注释模板 软件:idea 版本:2019.3.1 1.在idea中设置类模板 /** * @Class ...
- 基于TCP实现简单的聊天室
原文出处:<Go 语言编程之旅>第四章4.1节 基于TCP的聊天室 1.服务端 新用户到来,生成一个User的实例,代表该用户. type User struct{ ID int // 用 ...
- Solon AI 五步构建 RAG 服务:2025 最新 AI + 向量数据库实战
此文参考自:https://www.toutiao.com/article/7506140643970826779/ 引言:RAG 会成为 2025 年 AI 落地核心? 在2025年,检索增强生成( ...
- 从零开始实现简易版Netty(一) MyNetty Reactor模式
从零开始实现简易版Netty(一) MyNetty Reactor模式 自从18年作为一个java程序员入行以来,所接触到的大量组件如dubbo.rocketmq.redisson等都是基于netty ...
- 工程师都喜欢的一款自动生成网格的仿真软件——Hyperworks到底好不好用?
HyperWorks是一款广泛应用于工程仿真和优化的软件平台,其中包括了许多强大的工具和功能.其中的网格自动生成工具是其重要组成部分之一,对于工程仿真和优化来说具有重要的意义.那么,HyperWork ...
- 盘古信息PCB行业解决方案:以全域场景重构,激活智造新未来
一.破局:PCB行业的时代之问 在数字经济蓬勃发展的浪潮中,PCB(印制电路板)作为 "电子产品之母",其重要性愈发凸显.随着 5G.人工智能等新兴技术的加速渗透,PCB行业面临着 ...
- 《Building REST APIs with Flask》读后感
一. 为什么读这本书? 之所以选择这本书其实是因为最近自己在梳理 JWT 的用法.自己曾参与过的一个项目虽然使用的是 Flask 开发,但是授权使用的 PyJWT,当时以为使用 PyJWT 是行业通用 ...
- Jfinal启动报错-文件找不到