【多线程学习笔记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一个线程对象了,所以之前即使有用到,也更多时候都是用的懵懵的。


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

相关文章
|
6天前
|
监控 安全 Java
【多线程学习】深入探究阻塞队列与生产者消费者模型和线程池常见面试题
【多线程学习】深入探究阻塞队列与生产者消费者模型和线程池常见面试题
|
6天前
|
缓存 安全 Java
多线程--深入探究多线程的重点,难点以及常考点线程安全问题
多线程--深入探究多线程的重点,难点以及常考点线程安全问题
|
6天前
|
数据采集 安全 Java
Python的多线程,守护线程,线程安全
Python的多线程,守护线程,线程安全
|
10天前
|
监控 Java 调度
Java多线程实战-从零手搓一个简易线程池(四)线程池生命周期状态流转实现
Java多线程实战-从零手搓一个简易线程池(四)线程池生命周期状态流转实现
|
10天前
|
设计模式 Java
Java多线程实战-从零手搓一个简易线程池(三)线程工厂,核心线程与非核心线程逻辑实现
Java多线程实战-从零手搓一个简易线程池(三)线程工厂,核心线程与非核心线程逻辑实现
|
10天前
|
Java 测试技术
Java多线程实战-从零手搓一个简易线程池(二)线程池实现与拒绝策略接口定义
Java多线程实战-从零手搓一个简易线程池(二)线程池实现与拒绝策略接口定义
|
10天前
|
存储 安全 Java
Java多线程实战-从零手搓一个简易线程池(一)定义任务等待队列
Java多线程实战-从零手搓一个简易线程池(一)定义任务等待队列
|
26天前
|
存储 Java 数据库连接
java多线程之线程通信
java多线程之线程通信
|
10天前
|
存储 消息中间件 Java
Java多线程实战-异步操作日志记录解决方案(AOP+注解+多线程)
Java多线程实战-异步操作日志记录解决方案(AOP+注解+多线程)
|
10天前
|
缓存 Java 测试技术
Java多线程实战-实现多线程文件下载,支持断点续传、日志记录等功能
Java多线程实战-实现多线程文件下载,支持断点续传、日志记录等功能

相关实验场景

更多