10 张图聊聊线程的生命周期和经常使用 APIs

今天咱们来讲一下线程的生命周期和经常使用 APIs:咱们须要很是清楚的知道线程的各类状态,好比排查程序运行慢的缘由时,就须要看下是否是哪里被阻塞了;另外它也是面试时很是喜欢问的,若是基础内容都答很差,恐怕直接就挂了。java

本文分为两大部分,面试

1.线程的 6 大状态;安全

2.多线程经常使用的 APIs:微信

  • join()多线程

  • wait()并发

  • notify()ide

  • yield()this

  • sleep()spa

  • currentThread()线程

  • getName()

  • getId()

  • getPriority()

  • setPriority()

  • stop()

线程状态

关于线程的状态,网上各类说法都有,比较流行的是 5 种或者 6 种。关于 5 种状态的那个版本我没有找到理论依据,若是有小伙伴清楚的也欢迎留言指出。

我这里所写的是根据 java.lang.Thread 的源码,线程有如下 6 大状态:

public enum State {   NEW,   RUNNABLE,   BLOCKED,   WAITTING,   TIMED_WAITTING,   TERMINATED; }

先上图,咱们再依次来看。

1. New

A thread that has not yet started is in this state.

就是指线程刚建立,还没启动的时候,好比刚 new 了一个 thread。

MyThread myThread = new MyThread();

2. Runnable

A thread is executing in the Java virtual machine but it may be waiting for other resources from the operating system such as processor.

那么接下来,天然就是要启动线程了,也就是调用 thread 的 start() 方法。

myThread.start();

启动以后,线程就进入了 Runnable 状态。

此时全部的线程都会添加到一个等待队列里,等待“CPU 调度”。

若是抢占到 CPU 的资源,那就执行;若是没抢到,就等着呗,等当前正在执行的线程完成它能执行的时间片以后,再次抢占。

要注意这里在等待的通常是系统资源,而不是锁或者其余阻塞。

3. Blocked

Thread state for a thread blocked waiting for a monitor lock.

A thread in the blocked state is waiting for a monitor lock to enter a synchronized block/method or reenter a synchronized block/method after calling wait() Object.

这里给出了很是明确的 use case,就是被锁在外面的才叫阻塞。因此这里必需要有至少 2 个线程。

4. Waiting

A thread in the waiting state is waiting for another thread to perform a particular action.

那具体有哪些缘由呢?

A thread is in the waiting state due to calling one of the following methods:

  • Object.wait with no timeout

  • Thread.join with no timeout

  • LockSupport.park

因此说,当调用了

  • wait(),

  • join(),

  • park()

方法以后,线程进入等待状态。

这里的等待状态是没有时间限制的,能够无限的等下去... 因此须要有人来唤醒:

若是是经过 wait() 进入等待状态的,须要有 notify() 或者 notifyAll() 方法来唤醒;

若是是经过 join() 进入等待状态的,须要等待目标线程运行结束。

好比在生产者消费者模型里,当没有商品的时候,消费者就须要等待,等待生产者生产好了商品发 notify()。下一篇文章咱们会细讲。

5. Timed_waiting

致使这个状态的缘由以下:

  • Thread.sleep

  • Object.wait with timeout

  • Thread.join with timeout

  • LockSupport.parkNanos

  • LockSupport.parkUntil

其实就是在上一种状态的基础上,给了具体的时间限制。

那么当时间结束后,线程就解放了。

6. Terminated

A thread that has exited is in this state.

这里有 3 种状况会终止线程:

  • 执行完全部代码,正常结束;

  • 强制被结束,好比调用了 stop() 方法,如今已经被弃用;

  • 抛出了未捕获的异常。

线程一旦死亡就不能复生。

若是在一个死去的线程上调用 start() 方法,那么程序会抛出 java.lang.IllegalThreadStateException。

接下来咱们说说多线程中经常使用的 11 个 APIs。

APIs

1. join()

join() 方法会强制让该线程执行,而且一直会让它执行完。

好比上一篇文章的例子是两个线程交替执行的,那么咱们这里该下,改为调用小齐线程.join(),那么效果就是先输出 小齐666。

public class MyRunnable implements Runnable {     @Override     public void run() {         for(int i = 0; i < 100; i++) {             System.out.println("小齐666:" + i);         }     }      public static void main(String[] args) throws InterruptedException {         Thread t = new Thread(new MyRunnable());         t.start();         t.join();          for(int i = 0; i < 100; i++) {             System.out.println("主线程" + i + ":齐姐666");         }     } }

因此 join() 可以保证某个线程优先执行,并且会一直让它执行完,再回归到公平竞争状态。

join() 方法实际上是用 wait() 来实现的,咱们来看下这个方法。

2. wait() and notify()

wait() 其实并非 Thread 类的方法,而是 Object 里面的方法。

该方法就是让当前对象等待,直到另外一个对象调用 notify() 或者 notifyAll()。

固然了,咱们也能够设定一个等待时长,到时间以后对象将会自动苏醒。

4. yield()

yield 自己的中文意思是屈服,用在这里倒也合适。

yield() 表示当前线程主动让出 CPU 资源一下,而后咱们再一块儿去抢。

注意这里让一下真的只是一下,从“执行中”回到“等待 CPU 分配资源”,而后全部线程再一块儿抢占资源。

5. sleep()

顾名思义,这个方法就是让当前线程睡一会,好比说,

myThread.sleep(1000); // 睡眠 1 秒钟

它会抛出一个 InterruptedException 异常,因此还要 try catch 一下。

6. currentThread()

Returns a reference to the currently executing thread object.

该方法是获取当前线程对象。

注意它是一个 static 方法,因此直接经过 Thread 类调用。

好比打印当前线程

System.out.println(Thread.currentThread());

前文的例子中,它会输出:

Thread[Thread-0,5,main] Thread[main,5,main]

没错,它的返回值也是 Thread 类型。

7. getName()

该方法能够获取当前线程名称。

这个名称能够本身设置,好比:

Thread t = new Thread(new MyRunnable(), "壹齐学");

8. getId()

该方法是获取线程的 Id.

9. getPriority()

线程也有优先级的哦~

虽然优先级高的线程并不能百分百保证必定会先执行,但它是有更大的几率被先执行的。

优先级的范围是 1-10,咱们来看源码:

/**     * The minimum priority that a thread can have.     */    public final static int MIN_PRIORITY = 1;    /**     * The default priority that is assigned to a thread.     */    public final static int NORM_PRIORITY = 5;     /**     * The maximum priority that a thread can have.     */    public final static int MAX_PRIORITY = 10;

若是不在这个范围,JDK 抛出 IllegalArgumentException() 的异常。

10. setPriority()

固然啦,咱们也是能够本身设置某个线程的优先级的。

设置的优先级也须要在规定的 1-10 的范围内哦,若是不在这个范围也会抛异常。

11. stop()

最后咱们来讲下 stop() 方法,也是前文提到过的强制中止线程的一种方式,但如今已被弃用,由于会引发一些线程安全方面的问题。

好了,以上就是有关线程状态和经常使用 API 的介绍了。相信你们看完以后对线程的整个流程应该有了清晰的认识,其实里面还有不少细节我没有展开,毕竟这是多线程的第 2 讲,更深刻的内容咱们慢慢来。

本文转载自微信公众号「 码农田小齐」,能够经过如下二维码关注。转载本文请联系 码农田小齐公众号。

【编辑推荐】

  1. 微软延长Windows 10版本1803的生命周期:再多活6个月

  2. 拜托!别再问我多线程的这些问题了

  3. 你真的知道什么是线程安全吗?

  4. Java 并发之线程池

  5. Java多线程知多少

【责任编辑:武晓燕 TEL:(010)68476606】