Java多线程技能总结
一: 多线程的概念
1.线程是依赖于进程的, 进程,正在运行的程序。是系统进行资源分配和调用的独立单位。每一个进程都有它自己的内存空间和系统资源,在同一个进程内又可以执行多个任务,而每一个任务我们就可以看成是一个线程,这就是多线程。
二: 实现多线程的方式
Java 5以前实现多线程有两种实现方法:一种是继承Thread类;另一种是实现Runnable接口。两种方式都要通过重写run()方法来定义线程的行为,推荐使用后者,因为Java中的继承是单继承,一个类有一个父类,如果继承了Thread类就无法再继承其他类了,显然使用Runnable接口更为灵活。
这两种方式都是调用线程对象的start()方法来启动该线程。
此外,还有第三种方式:通过Callable和Future创建线程
(1)创建Callable接口的实现类,并实现call()方法,该call()方法将作为线程执行体,并且有返回值。
(2)创建Callable实现类的实例,使用FutureTask类来包装Callable对象,该FutureTask对象封装了该Callable对象的call()方法的返回值。
(3)使用FutureTask对象作为Thread对象的target创建并启动新线程。
(4)调用FutureTask对象的get()方法来获得子线程执行结束后的返回值。
创建线程的三种方式的对比:
采用实现Runnable、Callable接口的方式创建多线程时,优势是:
线程类只是实现了Runnable接口或Callable接口,还可以继承其他类。
在这种方式下,多个线程可以共享同一个target对象,所以非常适合多个相同线程来处理同一份资源的情况,从而可以将CPU、代码和数据分开,形成清晰的模型,较好地体现了面向对象的思想。
劣势是:
编程稍微复杂,如果要访问当前线程,则必须使用Thread.currentThread()方法。
使用继承Thread类的方式创建多线程时优势是:
编写简单,如果需要访问当前线程,则无需使用Thread.currentThread()方法,直接使用this即可获得当前线程。
劣势是:
线程类已经继承了Thread类,所以不能再继承其他父类。
三: 线程的常用方法
1. currentThread() 方法:返回代码段正在被哪个线程调用,如Thread.currentThread().getName(),获取调用代码段线程的名称。
2 isAlive() 方法:判断当前线程是否处于活动状态。活动状态指 线程已经启动且尚未终止。线程处于正在运行或者准备开始运行的状态,则认为线程是"存活"的。
3 sleep() 方法:在指定的毫秒数内让当前“正在执行的线程”休眠,“正在执行的线程”指 this.currentThread() 返回的线程。
4 getId():取得线程的唯一标识。
停止线程的方法:
https://blog.csdn.net/cy_alone/article/details/69855700 其中介绍了停止线程的方法以及关闭线程池中线程的方法
1 interrupt
interrupt方法用于中断线程。调用该方法的线程的状态为将被置为"中断"状态。
注意:线程中断仅仅是置线程的中断状态位,不会停止线程。需要用户自己去监视线程的状态为并做处理。支持线程中断的方法(也就是线程中断后会抛出interruptedException的方法)就是在监视线程的中断状态,一旦线程的中断状态被置为“中断状态”,就会抛出中断异常。
2 interrupted 以及isinterrupted
https://blog.csdn.net/github_34889651/article/details/52474869
这篇文章 以举例和官方文档的形式,生动的介绍了这两个方法。 读后理解到:interrupted是指获取 当前 线程的是否中断状态,并清除了这一标志位,而isInterrupted只是获取线程的是否中断状态,并不会对状态标志位有什么影响。
结合以上两篇文章,可以对着三个方法有深刻的理解啦!~
3 线程池的关闭
shutDown():
当线程池调用该方法时,线程池的状态则立刻变成SHUTDOWN状态。此时,则不能再往线程池中添加任何任务,否则将会抛出RejectedExecutionException异常。但是,此时线程池不会立刻退出,直到添加到线程池中的任务都已经处理完成,才会退出。
shutdownNow():
根据JDK文档描述,大致意思是:执行该方法,线程池的状态立刻变成STOP状态,并试图停止所有正在执行的线程,不再处理还在池队列中等待的任务,当然,它会返回那些未执行的任务。
它试图终止线程的方法是通过调用Thread.interrupt()方法来实现的,但是大家知道,这种方法的作用有限,如果线程中没有sleep 、wait、Condition、定时锁等应用, interrupt()方法是无法中断当前的线程的。所以,ShutdownNow()并不代表线程池就一定立即就能退出,它可能必须要等待所有正在执行的任务都执行完成了才能退出。
suspend方法与resume方法:
suspend()方法就是将一个线程挂起(暂停),resume()方法就是将一个挂起线程复活继续执行。
值得一提的是 suspend()这个 暂停方法 和sleep()一样 都是不释放锁的。
yield方法:
Thread.yield()方法作用是:暂停当前正在执行的线程对象,并执行其他线程。
yield()应该做的是让当前运行线程回到可运行状态,以允许具有相同优先级的其他线程获得运行机会。因此,使用yield()的目的是让相同优先级的线程之间能适当的轮转执行。但是,实际中无法保证yield()达到让步目的,因为让步的线程还有可能被线程调度程序再次选中。 结论:yield()从未导致线程转到等待/睡眠/阻塞状态。在大多数情况下,yield()将导致线程从运行状态转到可运行状态,但有可能没有效果。
四:线程的优先级以及守护线程
https://blog.csdn.net/Silent_Paladin/article/details/54563470 介绍守护线程
https://blog.csdn.net/luckey_zh/article/details/46958493 介绍线程的优先级