6.1Thread常见属性
属性 | 获取方法 |
---|---|
ID | getId |
名称 | getName |
状态 | getState |
优先级 | getPriority |
是否后台线程 | isDaemon |
是否存活 | isAlive |
是否被中断 | isInterrupted |
ID 是线程的唯一标识,不同线程不会重复
名称是各种调试工具用到
状态表示线程当前所处的一个情况,下面我们会进一步说明
优先级高的线程理论上来说更容易被调度到
后台线程:守护线程,后台线程结束与否不影响整个程序,但如果前台线程没有结束,进程也不会结束。
是否存活:判断内核线程是否已经销毁
6.2 中段一个线程- interrupt()
首先我们要知道,一个线程如果时间特别长,那么大概率在线程的内部有循环再一直执行。如果想要中断此线程,那么我们就想办法尽快让run函数执行完成,那么怎么能让循环快速执行完呢?其实我们只需要在循环处添加一个条件,条件不成立就结束了。
例如:
public class Demo7 {
public static boolean flag=false;
public static void main(String[] args) throws InterruptedException {
Thread t=new Thread(()->{
while (!flag){
System.out.println("t进程");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("工作完毕");
});
t.start();
Thread.sleep(5000);
flag=true;
System.out.println("打断进程");
}
}
注意
定义flag的时候只能定义为成员变量,不能定义为局部变量,因为在lambda有一个语法规则:变量捕获。把当前作用域的变量在lambda中复制了一份,在变量捕获时有一个前提限制:必须只能捕获final修饰的变量或者变量不能做任何修改。如果把flag设置为成员变量,就不再是变量捕获的与法律,而是内部类访问外部类的属性。
但是如果我们每次都专门定义一个标志位来打断线程是非常麻烦的,而且当处于睡眠模式下还不能立即就想应,在Thread类中有有一个标志位isInterupted来判定线程是否被打断。
public class Demo8 {
public static void main(String[] args) throws InterruptedException {
Thread t=new Thread(()->{
while (!Thread.currentThread().isInterrupted()){
System.out.println("t进程");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
//唤醒sleep有3种操作
//1.不管它,继续执行t线程
//2.立即执行打断
break;
//3.进行一些其他操作
}
}
});
t.start();
System.out.println("main进程");
Thread.sleep(5000);
System.out.println("t进程打断");
t.interrupt();//打断
}
}
说明
1.Thread.currentThread()表示当前线程即t线程
2.在正常情况下,sleep休眠时间完成才会被唤醒,如果调用interrupt()那么就提提前唤醒它触发InterruptedException异常
观察下图:虽然打断了t线程并且触发了InterruptedException异常,但t线程依然在执行。
出现上述情况是因为:interr唤醒sleep之后会抛出异常当同时也会清除标志位,这就使打断效果像没有生效一样。Java期望当线程收到“要中断”的信号使,由本身来决定接下来该怎么做。
6.3等待线程-jion()
等待一个线程即使指,当一个线程执行完毕时才能执行另外一个线程。
public class Demo9 {
public static void main(String[] args) throws InterruptedException {
Thread t=new Thread(()->{
for (int i=0;i<5;i++){
System.out.println("t线程正在执行");
}
});
t.start();
//等待t线程执行结束再执行main线程
t.join();
System.out.println("t线程执行结束");
System.out.println("main线程");
}
}