基础
线程的声明周期
Java 线程既然能够创建,那么也势必会被销毁,所以线程是存在生命周期的,可以从线程的生命周期开始去了解线程
线程一共有 6 种状态:NEW、RUNNABLE、BLOCKED、WAITING、TIME_WAITING、TERMINATED
NEW:初始状态,线程被构建,但是还没有调用 start 方法
RUNNABLE:运行状态,JAVA 线程把操作系统中的就绪和运行两种状态统一称为“运行中”
BLOCKED:阻塞状态,表示线程进入等待状态,也就是线程因为某种原因放弃了 CPU 使用权,阻塞也分为几种情况
1)等待阻塞:运行的线程执行 wait 方法,jvm 会把当前线程放入到等待队列
2)同步阻塞:运行的线程在获取对象的同步锁时,若该同步锁被其他线程锁占用了,那么 jvm 会把当前的线程放入到锁池中
3)其他阻塞:运行的线程执行 Thread.sleep 或者 t.join 方法,或者发出了 I/O 请求时,JVM 会把当前线程设置为阻塞状态,当 sleep 结束、join 线程终止、io 处理完毕则线程恢复
WAITING:等待状态
TIMED_WAITING:超时等待状态,超时以后自动返回
TERMINATED:终止状态,表示当前线程执行完毕

演示代码的状态:
public class ThreadStatus {
public static void main(String[] args) {
//TIME_WAITING
new Thread(()->{
while(true){
try {
TimeUnit. SECONDS .sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"timewaiting").start();
//WAITING,线程在 ThreadStatus 类锁上通过 wait 进行等待
new Thread(()->{
while(true){
synchronized (ThreadStatus.class){
try {
ThreadStatus.class.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
},"Waiting").start();
//线程在 ThreadStatus 加锁后,不会释放锁
new Thread(new BlockedDemo(),"BlockDemo-01").start();
new Thread(new BlockedDemo(),"BlockDemo-02").start();
}
static class BlockedDemo extends Thread{
public void run(){
synchronized (BlockedDemo.class){
while(true){
try {
TimeUnit. SECONDS .sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
}
启动一个线程前,最好为这个线程设置线程名称,因为这样在使用 jstack 分析程序或者进行问题排查时,就会给开发人员提供一些提示
线程的生命周期,在整个生命周期中并不是固定的处于某个状态,而是随着代码的执行在不同的状态之间进行切换
线程启动的原理
线程的启动,也就是调用start()方法去启动一个线程,当 run 方法中的代码执行完毕以后,线程的生命周期也将终止。调用 start 方法的语义是当前线程告诉 JVM,启动调用 start 方法的线程
线程的应用
如何应用多线程?
在 Java 中,有多种方式来实现多线程:继承 Thread 类、实现 Runnable 接口、使用 ExecutorService、Callable、Future 实现带返回结果的多线程
- 继承Thread类创建线程
Thread 类本质上是实现了 Runnable 接口的一个实例,代表一个线程的实例。启动线程的唯一方法就是通过 Thread类的 start()实例方法。start()方法是一个 native 方法,它会启动一个新线程,并执行 run()方法
这种方式实现多线程很简单,通过自己的类直接 extend Thread,并复写 run()方法,就可以启动新线程并执行自己定义的 run()方法
- 实现Runnable接口创建线程
如果自己的类已经 extends 另一个类,就无法直接 extends
Thread,此时,可以实现一个 Runnable 接口
public class MyThread extends OtherClass implements Runnable {
public void run() {
System.out.println("MyThread.run()");
}
}
- 实现 Callable 接口(call方法)通过 FutureTask 包装器来创建 Thread 线程
public class CallableDemo implements Callable {
public static void main(String[] args) throws ExecutionException, InterruptedException {
ExecutorService executorService = Executors.newFixedThreadPool(1);
CallableDemo callableDemo=new CallableDemo();
Future<String> future=executorService.submit(callableDemo);
System. out .println(future.get());
executorService.shutdown();
}
@Override
public Object call() throws Exception {
int a=1;
int b=2;
System. out .println(a+b);
return "执行结果:"+(a+b);
}
}
网友评论