在线客服
扫描二维码
下载博学谷APP扫描二维码
关注博学谷微信公众号
Java支持多线程编程,因此用Java编写的应用程序可以同时执行多个任务。Java的多线程机制使用起来非常方便,用户只需关注程序细节的实现,而不用担心后台的多任务系统。本文将为大家讲解有关Java多线程的基础知识,主要内容有多线程的概念、创建、优势和生命周期。
1、什么是多线程
在早期的计算机中时没有操作系统的,计算机开启后只能执行一个程序,直到结束。操作系统的出现使得计算机可以同时执行多个程序,操作系统为每个程序分配不同的进程,每个进程拥有独立的句柄、资源等,使得计算机可以同时执行多个程序。但是进程的创建和销毁耗费的代价太大,因此衍生出线程的概念。允许在一个进程中创建多个线程,这些线程共享进程的资源,并且每个线程拥有自己独立的程序计数器、线程局部变量等资源。线程也被称为进程的轻量型运动实体。
2、创建多线程和启动
(1)继承Thread类创建线程类
通过继承Thread类创建线程类的具体步骤和具体代码如下:
定义一个继承Thread类的子类,并重写该类的run()方法;
创建Thread子类的实例,即创建了线程对象;
调用该线程对象的start()方法启动线程。
class SomeThead extends Thraad {
public void run() {
//do something here
}
}
public static void main(String[] args){
SomeThread oneThread = new SomeThread();
步骤3:启动多线程:
oneThread.start();
}
(2)实现Runnable接口创建线程类
通过实现Runnable接口创建线程类的具体步骤和具体代码如下:
定义Runnable接口的实现类,并重写该接口的run()方法;
创建Runnable实现类的实例,并以此实例作为Thread的target对象,即该Thread对象才是真正的线程对象。
class SomeRunnable implements Runnable {
public void run() {
//do something here
}
}
Runnable oneRunnable = new SomeRunnable();
Thread oneThread = new Thread(oneRunnable);
oneThread.start();
(3)通过Callable和Future创建线程
通过Callable和Future创建线程的具体步骤和具体代码如下:
创建Callable接口的实现类,并实现call()方法,该call()方法将作为线程执行体,并且有返回值。
创建Callable实现类的实例,使用FutureTask类来包装Callable对象,该FutureTask对象封装了该Callable对象的call()方法的返回值。
使用FutureTask对象作为Thread对象的target创建并启动新线程。
调用FutureTask对象的get()方法来获得子线程执行结束后的返回值其中,Callable接口(也只有一个方法)定义如下:
public interface Callable {
V call() throws Exception;
}
步骤1:创建实现Callable接口的类SomeCallable(略);
步骤2:创建一个类对象:
Callable oneCallable = new SomeCallable();
步骤3:由Callable创建一个FutureTask对象:
FutureTask oneTask = new FutureTask(oneCallable);
注释: FutureTask是一个包装器,它通过接受Callable来创建,它同时实现了 Future和Runnable接口。
步骤4:由FutureTask创建一个Thread对象:
Thread oneThread = new Thread(oneTask);
步骤5:启动线程:
oneThread.start();
3、多线程的优势
多线程的出现带来很多的好处:
(1)发挥多核处理器的性能:在多喝处理器上执行单线程任务是对多核的浪费,因为总有核心在空闲着,多线程的出现能充分发挥多核的优势。
(2)化整为零:往往在一个复杂的应用中包含许多不同类型的任务,将这些不同类型的任务分配给不同的线程去执行会比将其混在同一个线程中去执行要好,因为每个线程更加的简单清晰,更容易测试等。
(3)异步事件处理:当一个线程处理的任务遇到阻塞时如IO阻塞,cpu可以调度其他线程去执行而不是在那傻傻的等到IO结束在执行其他任务。
(5)更好的用户体验:当多个用户像你的服务发送请求时,你一个线程依次执行任务会使得排在后面的用户等待时间过长得不到响应,带来不好的体验。但使用多个线程可以让每个用户都能很快的得到响应(尽管这不能高执行速度),用户会觉得自己的请求正在被处理,获得更好的体验。
4、多线程的生命周期
(1)新建状态
用new关键字和Thread类或其子类建立一个线程对象后,该线程对象就处于新生状态。处于新生状态的线程有自己的内存空间,通过调用start方法进入就绪状态(runnable)。
注意:不能对已经启动的线程再次调用start()方法,否则会出现Java.lang.IllegalThreadStateException异常。
(2)就绪状态
处于就绪状态的线程已经具备了运行条件,但还没有分配到CPU,处于线程就绪队列(尽管是采用队列形式,事实上,把它称为可运行池而不是可运行队列。因为cpu的调度不一定是按照先进先出的顺序来调度的),等待系统为其分配CPU。等待状态并不是执行状态,当系统选定一个等待执行的Thread对象后,它就会从等待执行状态进入执行状态,系统挑选的动作称之为“cpu调度”。一旦获得CPU,线程就进入运行状态并自动调用自己的run方法。
提示:如果希望子线程调用start()方法后立即执行,可以使用Thread.sleep()方式使主线程睡眠一伙儿,转去执行子线程。
(3)运行状态
处于运行状态的线程最为复杂,它可以变为阻塞状态、就绪状态和死亡状态。
处于就绪状态的线程,如果获得了cpu的调度,就会从就绪状态变为运行状态,执行run()方法中的任务。如果该线程失去了cpu资源,就会又从运行状态变为就绪状态。重新等待系统分配资源。也可以对在运行状态的线程调用yield()方法,它就会让出cpu资源,再次变为就绪状态。
注: 当发生如下情况是,线程会从运行状态变为阻塞状态:
①、线程调用sleep方法主动放弃所占用的系统资源
②、线程调用一个阻塞式IO方法,在该方法返回之前,该线程被阻塞
③、线程试图获得一个同步监视器,但更改同步监视器正被其他线程所持有
④、线程在等待某个通知(notify)
⑤、程序调用了线程的suspend方法将线程挂起。不过该方法容易导致死锁,所以程序应该尽量避免使用该方法。
当线程的run()方法执行完,或者被强制性地终止,例如出现异常,或者调用了stop()、desyory()方法等等,就会从运行状态转变为死亡状态。
(4)阻塞状态
处于运行状态的线程在某些情况下,如执行了sleep(睡眠)方法,或等待I/O设备等资源,将让出CPU并暂时停止自己的运行,进入阻塞状态。 在阻塞状态的线程不能进入就绪队列。只有当引起阻塞的原因消除时,如睡眠时间已到,或等待的I/O设备空闲下来,线程便转入就绪状态,重新到就绪队列中排队等待,被系统选中后从原来停止的位置开始继续运行。有三种方法可以暂停Threads执行:
(5)死亡状态
当线程的run()方法执行完,或者被强制性地终止,就认为它死去。这个线程对象也许是活的,但是,它已经不是一个单独执行的线程。线程一旦死亡,就不能复生。 如果在一个死去的线程上调用start()方法,会抛出java.lang.IllegalThreadStateException异常。
以上就是Java多线程的基础知识讲解,大家都了解了吗?这些基础知识大家都必须掌握,如果还有什么不明白的,可以报博学谷的Java课程,会有线上的专业老师为大家答疑解惑。
— 申请免费试学名额 —
在职想转行提升,担心学不会?根据个人情况规划学习路线,闯关式自适应学习模式保证学习效果
讲师一对一辅导,在线答疑解惑,指导就业!
相关推荐 更多
Java开发中进程和线程的区别是什么?
Java开发中进程和线程的区别是什么?进程是具有一定独立功能的程序关于某个数据集合上的一次 运行活动,进程是系统进行资源分配和调度的一个独立单位;线程自己基本上不拥有 系统资源,只拥有一点在运行中必不可少的资源。
9069
2019-06-04 10:40:05
Java基础学习之java序列化介绍
序列化是将对象的状态信息转换为可以储存或者传输的形式的过程。因此在Java开发中,序列化是一个非常重要的环节。Java序列化可以在JVM停止运行之后能够保存(持久化)制定的对象,并在将来重新读取被保存的对象。
6551
2019-06-25 18:26:59
Spring cloud eureka集群搭建教程
相信Spring cloud eureka集群搭建,对每一个Java学习者来讲都不陌生。想要进阶学习Java的学习者,都绕不开搭建Spring cloud eureka集群这一重要环节,同时这也是让很多人头疼的一个问题。本文就来为大家介绍一下博学谷的相关教程,希望能帮助到有这方面疑问的小伙伴。
5681
2019-11-01 19:14:07
成为Java架构师需要具备的基础知识有哪些?
行业中对于Java架构师的要求较高,需要掌握秒杀技术架构百万并发代理设计、动静分离架构思想、熔断限流实战、异步消息通信设计、垂直日志收集设计、秒杀冷热商品抢单实战、LVS+Nginx集群抢单百万并发实战等技术,入门学习了解可以先学习一下基础的部门。
4060
2020-11-20 14:46:09
Spring框架实现依赖注入操作步骤解析
Dependency Injection是spring框架核心 ioc 的具体实现。程序在编写时通过控制反转把对象的创建交给了spring,但是代码中不可能出现没有依赖的情况。ioc 解耦只是降低他们的依赖关系但不会消除,坐等框架把持久层对象传入业务层而不用我们自己去获取。
4335
2021-05-24 11:31:52