多线程初阶——线程状态
文章目录
1.Thread类及常见构造方法
给线程起名字
public class demo1 { public static void main(String[] args) { Thread t = new Thread(() -> { while(true){ System.out.println("Thread"); try { Thread.sleep(1000); } catch (InterruptedException e) { throw new RuntimeException(e); } } },"线程一"); t.start(); while (true){ System.out.println("main"); try { Thread.sleep(1000); } catch (InterruptedException e) { throw new RuntimeException(e); } } } }
2.Thread常见的方法
属性 | 方法 |
ID | getId() |
名称 | getName() |
状态 | getState() |
优先级 | getPriority() |
是否后台线程 | isDaemon() |
是否存活 | isAlive() |
是否被中断 | isInterrupted() |
说明
getId()
ID是线程唯一标识,不同线程不会重复
getName()
线程的名称
getState()
表示线程当前所处的一个情况
getPriority()
获得线程的优先级
isDaemon()
JVM会在一个进程的所有非后台线程结束后,才会结束运行,这里的后台,和我们常说的手机后台应用类似线程创建的时候,默认是一个前台线程,前台线程可以阻止进程的退出,后台线程不影响进程的退出
public class Demo5 { public static void main(String[] args) { Thread thread = new Thread(() -> { while (true) { System.out.println("thread..."); try { Thread.sleep(1000); } catch (InterruptedException e) { throw new RuntimeException(e); } } }); thread.start(); } }
由于线程是前台进程,需要等待运行结束,进程才结束。代码为死循环,所以将会一直执行。
利用setDaemom()
方法将线程设置为后台进程,等主线程执行完,进程就结束了,注意:先设置后台进程,再启动线程
public class Demo5 { public static void main(String[] args) { Thread thread = new Thread(() -> { while (true) { System.out.println("thread..."); try { Thread.sleep(1000); } catch (InterruptedException e) { throw new RuntimeException(e); } } }); thread.setDaemon(true); thread.start(); System.out.println("main....."); } }
3.线程相关的重要操作
3.1启动线程—start()
创建Thread
对象、重写run
方法,只是给线程安排了任务,并没有执行,而调用start
方法,才是创建出了线程
3.2中断线程
**线程结束其实就是让线程的入口方法执行完 **
而中断线程,其实就是让线程停止下来,结束入口方法的执行
有2种方法可以中断线程
**方法一:直接用自定义的变量来作为标志位 **
需要给标志位上加volatile
关键字
这里我们以李四在银行取钱为例
public class Demo8 { private static class MyRunnable implements Runnable { public volatile boolean isQuit = false; @Override public void run() { while (!isQuit) { System.out.println(Thread.currentThread().getName() + ": 别管我,我忙着转账呢!"); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println(Thread.currentThread().getName() + ": 啊!险些误了大事"); } } public static void main(String[] args) throws InterruptedException { MyRunnable target = new MyRunnable(); Thread thread = new Thread(target, "李四"); System.out.println(Thread.currentThread().getName() + ": 让李四开始转账。"); thread.start(); Thread.sleep(5 * 1000); System.out.println(Thread.currentThread().getName() + ": 老板来电话了,得赶紧通知李四对方是个骗子!"); target.isQuit = true; } }
方法二:使用Thread
自带的标志位
Thread.interrupted()
或者Thread.currenThread().isInterrupted()
public class Demo9 { private static class MyRunnable implements Runnable { @Override public void run() { while (!Thread.currentThread().isInterrupted()) { System.out.println(Thread.currentThread().getName() + ": 别管我,我忙着转账呢!"); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println(Thread.currentThread().getName() + ": 啊!险些误了大事"); } } public static void main(String[] args) throws InterruptedException { MyRunnable target = new MyRunnable(); Thread thread = new Thread(target, "李四"); System.out.println(Thread.currentThread().getName() + ": 让李四开始转账。"); thread.start(); Thread.sleep(5 * 1000); System.out.println(Thread.currentThread().getName() + ": 老板来电话了,得赶紧通知李四对方是个骗子!"); thread.interrupt(); } }
运行结果
这时抛出了InterruptedException
异常
这是为什么呢?
由于线程的有效任务是打印一句话,这个操作耗时比较小,大部分时间线程都在sleep
状态,正常来说,当线程在运行真正有效任务时去中断才是一个有效的中断,而在线程休眠的时候中断,其实是把休眠给中断了,而休眠本身没有到指定的时间,所以抛出了InterruptedException
异常
当我们去掉线程中的休眠时,结果如下
这时候线程才真正的中断了
3.3 等待线程— join()
我们知道线程之间的执行顺序是根据系统调度随机执行的,但有时我们需要等待一个线程执行完,再执行下一个线程,这时我们需要一个方法明确等待线程结束,
public class Demo10 { public static void main(String[] args) throws InterruptedException { Runnable target = () -> { for (int i = 0; i < 3; i++) { System.out.println(Thread.currentThread().getName() + ":正在工作!"); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println(Thread.currentThread().getName() + "结束了工作"); }; Thread thread1 = new Thread(target, "李四"); Thread thread2 = new Thread(target, "王五"); System.out.println("李四先工作"); thread1.start(); thread1.join(); System.out.println("李四结束了工作,王五开始工作"); thread2.start(); thread2.join(); System.out.println("王五结束了工作"); } }
join()其他方法
public void join() | 等待线程结束(一直等,知道线程执行的任务结束) |
public void join(long millis) | 等待线程结束,但等待millis毫秒 |
public void join(long millis, int nanos) | 同理 |
3.4 获取线程引用
private static Thread currentThread()
返回当前线程对象的引用
3.5休眠线程—sleep()
让线程休眠休眠一会
图解sleep()的具体使用
4.线程的状态
在Java线程分为6种状态
1. NEW:创建好了一个Java的Thread对象,并安排好了任务,没有调用start()方法之前,和PCB没有关系
2. RUNNABLE:运行+就绪状态,在执行任务时的一个常态之一
3. TIMED_WAITING:指定了一个时间的阻塞队列,过时不候
4. WAITING :没有指定时间的等待,一直死等
5. BLOCK:等待锁的状态
6. TERMINATED :结束,完成状态,PCB已经被销毁了,但是Java对象还在
查看线程状态
public class Demo14 { public static void main(String[] args) throws InterruptedException { Thread thread=new Thread(()->{ for (int i = 0; i < 5; i++) { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } }); System.out.println("线程创建之前:"+thread.getState()); thread.start(); Thread.sleep(1000); System.out.println("启动线程,创建好PCB后:"+thread.getState()); thread.join(); System.out.println("线程执行完成后:"+thread.getState()); } }
线程之间相互转换