【多线程学习笔记2】线程的创建与启动

简介: 【多线程学习笔记2】线程的创建与启动

1 线程的创建与启动



Java使用Thread类代表线程,所有的线程对象都必须是Thread类或其子类的实例。


1.1 继承Thread类创建线程类


通过继承Thread类来创建并启动多线程的步骤如下:


(1)定义Thread类的子类,并重写该类的run()方法,该run()方法的方法体就代表了线程需要完成的任务,因此把run()方法称为线程执行体。


(2)创建Thread子类的实例,即创建了线程对象。


(3)调用线程对象的start()方法来启动该线程。


注意:


(1)进行多线程编程时,不要忘记了Java程序运行时默认的主线程,main()方法的方法体就是主线程的线程执行体。


(2)使用继承Thread类的方法来创建线程类时,因为程序每次创建线程对象时都需要创建一个Thread子类的实例对象,所以多个线程之间无法共享线程类的实例变量。


1.2 实现Runnable接口创建线程类


使用Runnable接口来创建并启动多线程的步骤如下:


(1)定义Runnable接口的实现类,并重写该接口的run()方法,该run()方法的方法体就是该线程的线程执行体。


(2)创建Runnable实现类的实例,并以此实例作为Thread的target来创建Thread对象,该Thread对象才是真正的线程对象。


(3)调用线程对象的start()方法来启动该线程。


注意:


(1)Runnable对象仅仅作为Thread对象的target,Runnable实现类里包含的run()方法仅作为线程执行体。而实际的线程对象依然是Thread实例,只是该Thread线程负责执行其target的run()方法。


(2)采用Runnable接口的方式创建的多个线程可以共享线程类的实例变量,这是因为在这种方式下,程序所创建的Runnable对象只是线程的target,而多个线程可以共享同一个target,所以多个线程可以共享同一个线程类(实际上是线程的target类)的实例变量。


1.3 使用Callable和Future创建线程


通过实现Runnable接口创建多线程时,Thread类的作用就是把run()方法包装成线程执行体。


也许受此启发,从Java 5开始,Java提供了Callable接口,这个接口像是Runnable接口的增强,因为Callable接口提供了一个call()方法作为线程执行体,同时call()方法可以有返回值,而且可以声明并抛出异常。


同时Java 5提供了Future接口来代表Callable接口里call()方法的返回值,并为Future接口提供了一个FutureTask实现类,该实现类实现了Future接口,并实现了Runnable接口,也就是说它可以作为Thread类的target。


创建并启动有返回值的线程的步骤如下:


(1)创建Callable接口的实现类,并实现call()方法,该call()方法将作为线程执行体,且该call()方法有返回值,再创建Callable实现类的实例。


(2)使用FutureTask类来包装Callable对象,该FutureTask对象封装了该Callable对象的call()方法的返回值。


(3)使用FutureTask对象作为Thread对象的target创建并启动新线程。


(4)调用FutureTask对象的get()方法来获得子线程执行结束后的返回值。


1.4 创建线程的三种方式对比


通过继承Thread类或实现Runnable、Callable接口都可以实现多线程,不过实现Runnable接口与实现Callable接口的方式基本相同,只是Callable接口里定义的方法有返回值,可以声明抛出异常而已,所以这两个可以归为一类。那这种方式与继承Thread方式之间的主要差别如下。


采用实现Runnable、Callable接口的方式创建多线程的优缺点:


(1)线程类只是实现了Runnable接口或Callable接口,还可以继承其他类。


(2)这种方式下,多个线程可以共享同一个target对象,非常适合多个相同线程处理同一份资源的情况。


(3)劣势是编程稍显复杂,访问当前线程,必须使用Thread.currentThread()方法。

采用继承Thread类的方式创建多线程的优缺点:


(1)编写简单,若需要访问当前线程,无须使用Thread.currentThread()方法,直接使用this即可获得当前线程。


(2)劣势是,线程类已经继承了Thread类,就不能再继承其他父类了。


也是因为上面优劣势,一般是推荐采用实现Runnable接口、Callable接口的方式来创建多线程。对于不需要返回值的就用实现Runnable接口方式,对于需要返回值的就用实现Callable方式来创建。



写在最后的话:


搞开发这么多年了,多线程也用了蛮多了,对于多线程创建和启动的内容也学过很多遍了,但一直局限于应付面试,始终是有点蒙圈的。另外毕竟现在用多线程,都是依赖线程池,我是感觉很少自己直接去new一个线程对象了,所以之前即使有用到,也更多时候都是用的懵懵的。


这次再次学习并整理一下笔记,其实也是受了面试的启发。话说再一次学习,并回顾自己的开发经验,还是很大收获的。总结一下,也方便自己日后再复习回顾吧。

相关文章
|
10天前
|
Java 开发者
在Java多线程编程中,创建线程的方法有两种:继承Thread类和实现Runnable接口
【10月更文挑战第20天】在Java多线程编程中,创建线程的方法有两种:继承Thread类和实现Runnable接口。本文揭示了这两种方式的微妙差异和潜在陷阱,帮助你更好地理解和选择适合项目需求的线程创建方式。
12 3
|
10天前
|
Java 开发者
在Java多线程编程中,选择合适的线程创建方法至关重要
【10月更文挑战第20天】在Java多线程编程中,选择合适的线程创建方法至关重要。本文通过案例分析,探讨了继承Thread类和实现Runnable接口两种方法的优缺点及适用场景,帮助开发者做出明智的选择。
10 2
|
10天前
|
Java
Java中多线程编程的基本概念和创建线程的两种主要方式:继承Thread类和实现Runnable接口
【10月更文挑战第20天】《JAVA多线程深度解析:线程的创建之路》介绍了Java中多线程编程的基本概念和创建线程的两种主要方式:继承Thread类和实现Runnable接口。文章详细讲解了每种方式的实现方法、优缺点及适用场景,帮助读者更好地理解和掌握多线程编程技术,为复杂任务的高效处理奠定基础。
22 2
|
10天前
|
Java 开发者
Java多线程初学者指南:介绍通过继承Thread类与实现Runnable接口两种方式创建线程的方法及其优缺点
【10月更文挑战第20天】Java多线程初学者指南:介绍通过继承Thread类与实现Runnable接口两种方式创建线程的方法及其优缺点,重点解析为何实现Runnable接口更具灵活性、资源共享及易于管理的优势。
22 1
|
10天前
|
安全 Java 开发者
Java多线程中的`wait()`、`notify()`和`notifyAll()`方法,探讨了它们在实现线程间通信和同步中的关键作用
本文深入解析了Java多线程中的`wait()`、`notify()`和`notifyAll()`方法,探讨了它们在实现线程间通信和同步中的关键作用。通过示例代码展示了如何正确使用这些方法,并分享了最佳实践,帮助开发者避免常见陷阱,提高多线程程序的稳定性和效率。
22 1
|
10天前
|
Java
在Java多线程编程中,`wait()` 和 `notify()/notifyAll()` 方法是线程间通信的核心机制。
在Java多线程编程中,`wait()` 和 `notify()/notifyAll()` 方法是线程间通信的核心机制。它们通过基于锁的方式,使线程在条件不满足时进入休眠状态,并在条件成立时被唤醒,从而有效解决数据一致性和同步问题。本文通过对比其他通信机制,展示了 `wait()` 和 `notify()` 的优势,并通过生产者-消费者模型的示例代码,详细说明了其使用方法和重要性。
18 1
|
23天前
FFmpeg学习笔记(二):多线程rtsp推流和ffplay拉流操作,并储存为多路avi格式的视频
这篇博客主要介绍了如何使用FFmpeg进行多线程RTSP推流和ffplay拉流操作,以及如何将视频流保存为多路AVI格式的视频文件。
136 0
|
26天前
|
存储 消息中间件 资源调度
C++ 多线程之初识多线程
这篇文章介绍了C++多线程的基本概念,包括进程和线程的定义、并发的实现方式,以及如何在C++中创建和管理线程,包括使用`std::thread`库、线程的join和detach方法,并通过示例代码展示了如何创建和使用多线程。
38 1
C++ 多线程之初识多线程
|
2月前
|
数据采集 负载均衡 安全
LeetCode刷题 多线程编程九则 | 1188. 设计有限阻塞队列 1242. 多线程网页爬虫 1279. 红绿灯路口
本文提供了多个多线程编程问题的解决方案,包括设计有限阻塞队列、多线程网页爬虫、红绿灯路口等,每个问题都给出了至少一种实现方法,涵盖了互斥锁、条件变量、信号量等线程同步机制的使用。
LeetCode刷题 多线程编程九则 | 1188. 设计有限阻塞队列 1242. 多线程网页爬虫 1279. 红绿灯路口
|
26天前
|
存储 前端开发 C++
C++ 多线程之带返回值的线程处理函数
这篇文章介绍了在C++中使用`async`函数、`packaged_task`和`promise`三种方法来创建带返回值的线程处理函数。
42 6

相关实验场景

更多