@[TOC]多线程
什么是线程
线程就是一个“执行流”,每一个线程都能按照自己的代码执行顺序执行代码,能够实现多个线程同时执行多分代码,实现并发编程。
为什么使用线程
(1)并发编程的需要。单核CUP的发展已经到了瓶颈,我们想要提高CPU的算力已经非常困难,所以我们就需要多核CPU。而并发编程能更好的利用多核CPU
(2)有一些任务场景要等待IO,为了让等待IO的时间能够做其他工作,就需要并发编程
(3)虽然说,进程也能实现并发编程,创建和删除进程的过程比较消耗资源,反而线程比较轻量,更好实现并发编程。
线程的应用场景
(1)CPU密集的场景下,能够更充分利用多核资源
(2)IO密集的场景下,可以充分利用IO的等待时间,干点别的事情
进程和线程的区别
(1)进程包含线程,即线程是进程的一部分
(2)一个进程崩溃了,一般不会影响其他进程。而同一个进程中的一个线程崩溃了,一般会影响到其他线程,进而是该进程崩溃了。
(3)一个进程有自己的虚拟地址空间和文件描述符表,而同一个进程的多个线程则是共用相同的虚拟地址空间和文件描述符表。
(4)进程是操作系统资源分配的基本单位,而线程是操作系统调度的基本单位。
如何使用Java代码创建线程
【方法一】创建一个类,继承Thread类,实现run()方法
【方法二】创建一个类,实现Runnable接口,重写run()方法,来创建线程
【方法三】使用匿名内部类,创建Thread对象,重写run()方法,来创建线程
【方法四】使用匿名内部类,创建Runnable对象,重写run()方法,来创建线程
【方法五】使用lambda表达式,来创建线程
【方法六】创建Callable对象,实现call方法,在通过FutureTask对象辅助,来创建线程
【方法七】通过创建线程池,来实现多线程
Thread 类及常见方法
Thread常见的构造方法
Thread常见的方法
ID 是线程的唯一标识,不同线程不会重复
名称是各种调试工具用到
状态表示线程当前所处的一个情况,下面我们会进一步说明
优先级高的线程理论上来说更容易被调度到
关于后台线程,需要记住一点:JVM会在一个进程的所有非后台线程结束后,才会结束运行。
是否存活,即简单的理解,为 run 方法是否运行结束了
线程的中断问题,下面我们进一步说明
注意:线程可以分为前台线程和后台线程两种。前台线程:前台线程会阻止进程的结束,直到所有的线程都执行完后,进程才结束。例如:我们创建的线程和main线程都是前台线程。
后台线程:后台线程不会阻止进程结束,进程结束不管其他线程是否都完成自己的代码。我们可以通过Thread对象.setDaemon()来将线程设置为后台线程,注意:将线程设置为后台线程这一步要在启动线程之前,否则会报错。Thread对象.setDaemon(true) 表示设置为后台线程
如何启动线程
很多人会认为创建好一个Thread对象后,一个线程就启动了。这是一个很大的误区。创建好一个Thread对象只是将一个线程给创建好,并不是将一个线程启动了。我们想要启动一个线程 还要调用***start()***方法将线程启动。
中断线程
【方法一】自己设置一个标识位来中断线程
【方法二】使用Thread对象自己带的标识位 来中断线程
Thread.currentThread.isInterrupted()方法是判断该线程是否中断,true表示中断,false表示没有中断
Thread对象.interrupt()方法是将该线程中断。
Thread对象.interrupt()的行为:
(1)中断线程的时候,线程处在阻塞状态,那么将会抛出InterruptedException异常,所以,我们要进行异常处理。
(2)中断线程的时候,线程不处在阻塞状态,那么就会将线程里面的标识位的值设置位true;
等待一个线程–join()
我们说线程的调度是随机的,我们无法规定哪个线程先执行,但是,我们有办法哪个线程先执行完,哪个线程后执行完。使用join()方法就行。
join()方法的行为:在哪一个线程里调用 Thread对象,join(),则该线程就要等待调用join()方法的线程先执行完,该线程才能执行完。
例题:有三个线程A,B,C,我想让线程A在线程B之前完成,线程B在线程A之前完成。
获取当前线程的引用
我们通过Thread.currentThread()来获取当前线程的引用
Thread.currentThread()与类的this的用法是一样的。
在不同的线程中使用Thread.currentThread(),Thread.currentThread()就表示该线程的引用
休眠当前线程
我们想要休眠某个线程,就在该线程里调用Thread.sleep(休眠时间(单位ms))
Thread.sleep(休眠时间(单位ms))行为:将线程从就绪状态转变为阻塞状态,到达我们设置的时间后,线程的状态从阻塞状态变为就绪状态
线程的状态
线程的状态有六种:
(1)NEW:还没有安排工作
(2)RUNNABLE:可工作的,分为正在工作和即将工作
(3)TERMINATED:工作完成了
(4)TIMED_WAITING:阻塞状态,使用了sleep()方法
(5)WAITING:阻塞状态,使用了wait()方法
(6)BLOCKED:阻塞状态,