共计 3929 个字符,预计需要花费 10 分钟才能阅读完成。
上一篇文章 咱们聊了多线程的根底内容,比方为什么要应用多线程,线程和过程之间的不同,以及创立线程的 4 种形式。本文已收录至我的 Github: https://github.com/xiaoqi6666…
明天咱们来说一下线程的生命周期和罕用 APIs:咱们须要十分分明的晓得线程的各种状态,比方排查程序运行慢的起因时,就须要看下是不是哪里被阻塞了;另外它也是面试时十分喜爱问的,如果根底内容都答不好,恐怕间接就挂了。
本文分为两大部分,
- 线程的 6 大状态;
-
多线程罕用的 APIs:
- join()
- wait()
- notify()
- yield()
- sleep()
- 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 callingwait()
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 讲,更深刻的内容咱们慢慢来。
如果你喜爱这篇文章,记得给我点赞留言哦~你们的反对和认可,就是我创作的最大能源,咱们下篇文章见!
我是小齐,纽约程序媛,终生学习者,每天晚上 9 点,云自习室里不见不散!
更多干货文章见我的 Github: https://github.com/xiaoqi6666…**