乐趣区

关于java:10-张图聊聊线程的生命周期和常用-APIs

上一篇文章 咱们聊了多线程的根底内容,比方为什么要应用多线程,线程和过程之间的不同,以及创立线程的 4 种形式。本文已收录至我的 Github: https://github.com/xiaoqi6666…

明天咱们来说一下线程的生命周期和罕用 APIs:咱们须要十分分明的晓得线程的各种状态,比方排查程序运行慢的起因时,就须要看下是不是哪里被阻塞了;另外它也是面试时十分喜爱问的,如果根底内容都答不好,恐怕间接就挂了。

本文分为两大部分,

  1. 线程的 6 大状态;
  2. 多线程罕用的 APIs:

    1. join()
    2. wait()
    3. notify()
    4. yield()
    5. sleep()
    6. currentThread()
    7. getName()
    8. getId()
    9. getPriority()
    10. setPriority()
    11. 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.

那么接下来,天然就是要启动线程了,也就是调用 threadstart() 办法。

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()
    办法之后,线程进入期待状态。

这里的期待状态是没有工夫限度的,能够有限的等上来 … 所以须要有人来 唤醒

  1. 如果是通过 wait() 进入期待状态的,须要有 notify() 或者 notifyAll() 办法来唤醒;
  2. 如果是通过 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 讲,更深刻的内容咱们慢慢来。

如果你喜爱这篇文章,记得给我点赞留言哦~你们的反对和认可,就是我创作的最大能源,咱们下篇文章见!

我是小齐,纽约程序媛,终生学习者,每天晚上 9 点,云自习室里不见不散!

更多干货文章见我的 Github: https://github.com/xiaoqi6666…**

退出移动版