一.线程和进程
进程:操作系统资源资源分配的基本单位,占用的资源较大,进程间无共享内存,切换进程时,cpu消耗太多
线程:任务调度和执行的基本单位,一个进程可以有多个线程,线程之间公用所在进程的内存,资源共享。创建线程的开销较小。
二.线程的生命周期
线程总共有6种状态,分别如下:
1.新建状态(NEW):当创建一个线程对象的时候,线程处于该状态。
2.运行状态(RUNABLE):当调用线程的start方法时,线程处于该状态。该状态下有2个不同的子状态,分别是可运行和运行状态,当cpu调度当前线程的时候,线程状态为可运行状态,当cpu放弃当前线程或者当前线程执行yield操作时,该线程会重新进入可运行状态,等待cpu调度。
3.等待状态(WAITING和TIME_WAITING):两个状态唯一的区别就是是否加上时间参数,通过调用sleep,join,wait等方法进入该状态。
4.阻塞状态(BLOCKED):只有在执行到synchronized代码块,没有获取到锁的时候,会变成阻塞状态。
5.结束状态(TERMINATED):当前线程执行结束。
三.线程的创建方式
1.继承Thread
2.实现Runnable接口
3.实现fature/callable接口,带返回值的线程
4.从线程池中获取
四.线程的中断
如何正确停止一个线程,在java中,有提供stop,destory,suspend,resume方法,但是这些方法都已经被不推荐使用了。原因是强行终止一个线程,可能会导致当前线程里面的资源没有来得及释放,比如锁等等。这样会导致程序出现异常。
那么如何优雅的停止线程呢,可以通过jdk提供的interrupt标示来实现,jdk在native中维护了interrupt标示来判断当前线程是否能够继续执行
案例1:线程内部通过isInterrupted方法判断是否中断,调用方通过interrupt方法终止指定线程
public static void test1() throws InterruptedException {
Thread t1 = new Thread(() -> {
while (!Thread.currentThread().isInterrupted()) {
i++;
}
System.out.println("当前线程被中断,累计的和为:"+i);
}, "t1");
t1.start();
TimeUnit.SECONDS.sleep(1);
t1.interrupt();
}
输出结果:
案例2:同样在调用方调用interrupt中断程序之后,然后在线程中执行Thread.interrupted()重新将标示改成false
public static void test2() throws InterruptedException {
Thread t1 = new Thread(() -> {
while (!Thread.currentThread().isInterrupted()) {
System.out.println("线程执行中。。。");
}
System.out.println("线程被中断");
Thread.interrupted();
System.out.println("线程中断标示复位,当前标志为:"+Thread.currentThread().isInterrupted());
}, "t1");
t1.start();
TimeUnit.SECONDS.sleep(1);
t1.interrupt();
}
输出结果:
案例3:线程中catch了InterruptedException,然后在线程结束之前做一些资源处理
public static void test3() throws InterruptedException {
Thread t1 = new Thread(() -> {
while (true) {
try {
System.out.println("线程执行中。。。");
Thread.sleep(1000);
} catch (InterruptedException e) {
System.out.println("线程被中断");
System.out.println("对于中断之后抛出的异常可以进行相应的处理");
}
}
}, "t1");
t1.start();
TimeUnit.SECONDS.sleep(1);
t1.interrupt();
}
五.查看当前线程状态
public class Test {
public static void main(String[] args) {
new Thread(() -> {
while (true){
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"t1").start();
new Thread(() -> {
while (true){
synchronized (Test.class){
try {
//调用wait方法必须处于同步代码块中
Test.class.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
},"t2").start();
new Thread(new BlockDemo(),"blocked-1").start();
new Thread(new BlockDemo(),"blocked-2").start();
}
static class BlockDemo extends Thread{
@Override
public void run() {
synchronized (BlockDemo.class){
while (true){
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
}
进入命令行,输入jps查看所有正在进行的程序
当前正在测试的程序为Test,并且端口号为12320,执行命令jstack 12320查看该端口下所有线程的运行状态。
lingfandeMacBook-Pro:thread-demo lingfan$ jstack 12320
2019-09-23 20:15:25
Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.131-b11 mixed mode):
"Attach Listener" #18 daemon prio=9 os_prio=31 tid=0x00007fc7dd003800 nid=0x5903 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
"DestroyJavaVM" #17 prio=5 os_prio=31 tid=0x00007fc7dd9d6000 nid=0x1803 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
"blocked-2" #16 prio=5 os_prio=31 tid=0x00007fc7dd9d5800 nid=0x5803 waiting for monitor entry [0x0000700006ae4000]
java.lang.Thread.State: BLOCKED (on object monitor)
at com.example.threaddemo.Test$BlockDemo.run(Test.java:47)
- waiting to lock <0x000000076b157f78> (a java.lang.Class for com.example.threaddemo.Test$BlockDemo)
at java.lang.Thread.run(Thread.java:748)
"blocked-1" #14 prio=5 os_prio=31 tid=0x00007fc7dc050000 nid=0xa603 waiting on condition [0x00007000069e1000]
java.lang.Thread.State: TIMED_WAITING (sleeping)
at java.lang.Thread.sleep(Native Method)
at java.lang.Thread.sleep(Thread.java:340)
at java.util.concurrent.TimeUnit.sleep(TimeUnit.java:386)
at com.example.threaddemo.Test$BlockDemo.run(Test.java:47)
- locked <0x000000076b157f78> (a java.lang.Class for com.example.threaddemo.Test$BlockDemo)
at java.lang.Thread.run(Thread.java:748)
"t2" #12 prio=5 os_prio=31 tid=0x00007fc7dd9a4800 nid=0xa803 in Object.wait() [0x00007000068de000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x000000076acec9f8> (a java.lang.Class for com.example.threaddemo.Test)
at java.lang.Object.wait(Object.java:502)
at com.example.threaddemo.Test.lambda$main$1(Test.java:27)
- locked <0x000000076acec9f8> (a java.lang.Class for com.example.threaddemo.Test)
at com.example.threaddemo.Test$$Lambda$2/1237514926.run(Unknown Source)
at java.lang.Thread.run(Thread.java:748)
"t1" #11 prio=5 os_prio=31 tid=0x00007fc7dd002800 nid=0xa903 waiting on condition [0x00007000067db000]
java.lang.Thread.State: TIMED_WAITING (sleeping)
at java.lang.Thread.sleep(Native Method)
at java.lang.Thread.sleep(Thread.java:340)
at java.util.concurrent.TimeUnit.sleep(TimeUnit.java:386)
at com.example.threaddemo.Test.lambda$main$0(Test.java:15)
at com.example.threaddemo.Test$$Lambda$1/625576447.run(Unknown Source)
at java.lang.Thread.run(Thread.java:748)
"Service Thread" #10 daemon prio=9 os_prio=31 tid=0x00007fc7dd99f800 nid=0x4003 runnable [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
"C1 CompilerThread3" #9 daemon prio=9 os_prio=31 tid=0x00007fc7de008800 nid=0x4103 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
"C2 CompilerThread2" #8 daemon prio=9 os_prio=31 tid=0x00007fc7de008000 nid=0x4303 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
"C2 CompilerThread1" #7 daemon prio=9 os_prio=31 tid=0x00007fc7dd99f000 nid=0x4503 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
"C2 CompilerThread0" #6 daemon prio=9 os_prio=31 tid=0x00007fc7dd99e000 nid=0x4603 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
"Monitor Ctrl-Break" #5 daemon prio=5 os_prio=31 tid=0x00007fc7dd99c800 nid=0x3c03 runnable [0x00007000060c6000]
java.lang.Thread.State: RUNNABLE
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.socketRead(SocketInputStream.java:116)
at java.net.SocketInputStream.read(SocketInputStream.java:171)
at java.net.SocketInputStream.read(SocketInputStream.java:141)
at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:284)
at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:326)
at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:178)
- locked <0x000000076adcb058> (a java.io.InputStreamReader)
at java.io.InputStreamReader.read(InputStreamReader.java:184)
at java.io.BufferedReader.fill(BufferedReader.java:161)
at java.io.BufferedReader.readLine(BufferedReader.java:324)
- locked <0x000000076adcb058> (a java.io.InputStreamReader)
at java.io.BufferedReader.readLine(BufferedReader.java:389)
at com.intellij.rt.execution.application.AppMainV2$1.run(AppMainV2.java:64)
"Signal Dispatcher" #4 daemon prio=9 os_prio=31 tid=0x00007fc7df00a000 nid=0x3a03 runnable [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
"Finalizer" #3 daemon prio=8 os_prio=31 tid=0x00007fc7de80c800 nid=0x3503 in Object.wait() [0x0000700005ec0000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x000000076ab08ec8> (a java.lang.ref.ReferenceQueue$Lock)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:143)
- locked <0x000000076ab08ec8> (a java.lang.ref.ReferenceQueue$Lock)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:164)
at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:209)
"Reference Handler" #2 daemon prio=10 os_prio=31 tid=0x00007fc7de001000 nid=0x3403 in Object.wait() [0x0000700005dbd000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x000000076ab06b68> (a java.lang.ref.Reference$Lock)
at java.lang.Object.wait(Object.java:502)
at java.lang.ref.Reference.tryHandlePending(Reference.java:191)
- locked <0x000000076ab06b68> (a java.lang.ref.Reference$Lock)
at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:153)
"VM Thread" os_prio=31 tid=0x00007fc7dd804000 nid=0x4f03 runnable
t1线程执行sleep代码,状态为 java.lang.Thread.State: TIMED_WAITING (sleeping)。
t2线程执行wait代码,状态为 java.lang.Thread.State: WAITING (on object monitor)。
blocked-1线程抢夺到synchronized的锁,状态为 java.lang.Thread.State: TIMED_WAITING (sleeping)。
blocked-2线程没抢夺到synchronized的锁,状态为 java.lang.Thread.State: BLOCKED (on object monitor)。