一、概述
1.什么是线程?
线程就是同一个进程内的多条执行路径。所有的线程共享同一块内存空间地址,访问变量时,访问的就是同一个变量。
二、.线程的生命周期
1.新建状态:刚new出来的线程对象,还没调用start方法。
2.就绪状态:就绪状态也叫可运行状态,线程对象调用start方法进入就绪状态,等待抢占cpu资源。
3.运行状态:抢占CPU资源成功后,线程进行执行,进入到运行状态。
4.阻塞状态:在运行状态的线程可能因为sleep或者等待io、join进入到阻塞状态,当等待阻塞消失,会重新进入就绪状态,等待抢占cpu资源,当再次抢占到cpu资源时,则从上次停止的地方再次运行。
5.死亡状态:当线程正常运行完毕后或者抛出未捕获的异常,那么线程会进入到死亡状态。
三、线程的实现方式
线程有三种实现方式:Thread、Runnable、Callable
1.Thread的实现代码如下:
public class Thread1 extends Thread {
@Override
public void run() {
System.out.println("Thread方式创建线程");
}
public static void main(String[] args) throws InterruptedException {
new Thread1().start();
}
}
2.Runnable的实现代码如下:
public class Runnable1 implements Runnable {
@Override
public void run() {
System.out.println("Runnable方式创建线程");
}
public static void main(String[] args) {
new Thread(new Runnable1()).start();
}
}
3.Callable方式实现代码:
public class Callable1 implements Callable<String> {
@Override
public String call() throws Exception {
System.out.println("Callable方式创建线程");
return "Callable";
}
public static void main(String[] args) throws ExecutionException, InterruptedException {
FutureTask task=new FutureTask(new Callable1());//有参 赋值 成员属性
new Thread(task).start();
System.out.println(task.get());;
}
}
四、线程池
1.什么是线程池?
简单来说,线程池可以理解为一个“现成的池子”,里面有一定数量的线程等待工作,每次使用不用再次创建、使用完了不用马上销毁,会自动回收进池子中。类似常量池等等
虽然创建销毁线程比创建销毁进程更轻量, 但是在频繁创建销毁线程的时候还是会比较低效,线程池就是为了解决这个问题,如果某个线程不再使用了,并不是真正把线程释放,而是放到一个“池子”中,下次如果需要用到线程就直接从池子中取,不用再次创建。
2.线程池生命周期
通过查看ThreadPoolExecutor类源码,我们可以看到定义了5种线程池状态:
(1)Running:运行状态 能够接受新提交的任务,并且能够处理阻塞队列中的任务。
(2)SHUTDOWN:关闭状态,不再接受新提交的任务,能继续处理阻塞队列中的任务。
(3)STOP:停止状态,不再接受新的任务,也不处理阻塞队列中的任务,中断正在处理的任务线程。
(4)TIDYING: 整理状态 ,所有的任务都已经终止,workCount(有效线程数为0)。
(5)TERMINATED:终止状态 在terminated方法执行之后进入该状态。
注意:
1.线程池在构造前(new操作)是初始状态,一旦构造完成线程池就进入了执行状态RUNNING。严格意义上讲线程池构造完成后并没有线程被立即启动,只有进行“预启动”或者接收到任务的时候才会启动线程,但是线程池是处于运行状态,随时准备接受任务来执行。
2、线程池运行中可以通过shutdown()和shutdownNow()来改变运行状态。shutdown()是一个平缓的关闭过程,线程池停止接受新的任务,同时等待已经提交的任务执行完毕,包括那些进入队列还没有开始的任务,这时候线程池处于SHUTDOWN状态;shutdownNow()是一个立即关闭过程,线程池停止接受新的任务,同时线程池取消所有执行的任务和已经进入队列但是还没有执行的任务,这时候线程池处于STOP状态。
3、一旦shutdown()或者shutdownNow()执行完毕,线程池就进入TERMINATED状态,此时线程池就结束了。
3.线程池应用场景
- 商品秒杀
- 云盘文件上传和下载
- 异步发送邮件