网站建设的技术难点,食品类网站模板,教育培训类网站设计,app开发网站建设包含项目新内容开始之前,我们总结一个知识点. Thread类中的start方法和run方法的区别? start(): 用start方法来启动线程#xff0c;真正实现了多线程运行#xff0c;这时无需等待run方法体代码执行完毕而直接继续执行下面的代码。通过调用Thread类的start()方法来启动一个线程#… 新内容开始之前,我们总结一个知识点. Thread类中的start方法和run方法的区别? start(): 用start方法来启动线程真正实现了多线程运行这时无需等待run方法体代码执行完毕而直接继续执行下面的代码。通过调用Thread类的start()方法来启动一个线程这时此线程处于就绪可运行状态并没有运行 然后通过此Thread类调用方法run()来完成其运行操作的 这里方法run()称为线程体它包含了要执行的这个线程的内容 Run方法运行结束 此线程终止。然后CPU再调度其它线程。 一旦得到cpu时间片就开始执行run()方法这里方法 run()称为线程体它包含了要执行的这个线程的内容Run方法运行结束此线程随即终止. run(): run()方法只是类的一个普通方法而已如果直接调用Run方法程序中依然只有主线程这一个线程其程序执行路径还是只有一条还是要顺序执行还是要等待run方法体执行完毕后才可继续执行下面的代码这样就没有达到写线程的目的。 总结调用start方法方可启动线程而run方法只是thread的一个普通方法调用还是在主线程里执行。这两个方法应该都比较熟悉把需要并行处理的代码放在run()方法中start()方法启动线程将自动调用 run()方法这是由jvm的内存机制规定的。并且run()方法必须是public访问权限返回值类型为void。 目录 1. Thread 类的方法 2. 线程中断 2.1 设置一个结束标志位 2.2 interrupt() (Thread 中自带的标志位) 2.3 为什sleep要清空标志位? 3.线程等待 1. Thread 类的方法 2. 线程中断
线程的中断,就是将一个线程停下来.
线程的终止:本质上只有一种,就是让该线程的入口方法执行完毕.
2.1 设置一个结束标志位
/*** Created with IntelliJ IDEA.* Description:线程中断1-自己创建变量,控制循环* User: YAO* Date: 2023-05-08* Time: 16:28*/
public class ThreadDemo7 {public static boolean isQuit false;public static void main(String[] args) {Thread thread new Thread(()-{while (!isQuit){System.out.println(hello thread);try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}System.out.println(新线程结束);});thread.start();try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}isQuit true;}
}通过主线程进行修改标志位,使得新线程中的代码停止了循环. 思考:此时如果将isQuit,不写成成员变量,写在Main方法之中,还会达到想要的效果吗? 答案:不可以 虽然lambda表达式能够访问局部变量,但是lambda表达式有变量捕获,捕获的变量必须是没有进行修改过的变量,main方法中后面对isQuit做了修改,所以不可以写在main方法中.这个变量要么是被final修饰如果不是被final修饰的 你要保证在使用之前没有修改. 2.2 interrupt() (Thread 中自带的标志位)
public class ThreadDemo8 {public static void main(String[] args) {Thread thread new Thread(()-{//currentThread() 获取当前线程的实例while (!Thread.currentThread().isInterrupted()){System.out.println(hello t);try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();//打印当前异常位置的调用栈}}});thread.start();try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}//将标志位设置为truethread.interrupt();}
}简要介绍一下上面的代码. 首先认识两个方法: 1. Thread.currrentThread() :是获取当前线程的实例. 2. Thread.currrentThread() .isInterrupted() ---默认是false interrupt方法的作用:
* 1.设置标志位为true
* 2.如果该线程处于堵塞的状态(比如正在执行sleep),此时就会把阻塞状态给唤醒.通过抛出异常的方式让sleep立即结束.当我们运行上述代码的时候,我们会看见下述问题 出现的原因:
主线程中通过设置标志位interrupt,就立刻将sleep给唤醒,当sleep被唤醒的时候,sleep会自动的把isInterrupted标志位给清空 (true-flase),这样新线程的循环就被打通了,继续的执行sleep下一次遇见的时候就标志位就是false,那么就执行sleep本身,也不抛出异常,循环一直走下去,如果想要该循环截止,就在抛出异常的时候加一个break.
多线程的代码执行顺序不是“从上到下”而是每个线程独立执行的。
2.3 为什sleep要清空标志位? 清空标志位的目的是让线程本身能够对于线程何时结束有一个更明确的控制.
当前的interrupt方法效果并不是让线程立即结束而是告诉他你该结束了至于他是否真的要结束立即结束还是等会结束都是代码来灵活控制的。
interrupt只是建议不是命令。为什么java不强制设定为“命令结束”的操作呢只要调用interru就立即结束呢因为设定成这种非常不友好。线程t何时结束一定是t自己最清楚。交给t自己决定就比较好。
3.线程等待
使用thread.join()
线程之间是并发执行的。操作系统对于线程的调度是无序的无法判定两个线程谁先执行结束谁后执行结束。
package threading;public class ThreadDemo8 {public static void main(String[] args) {Thread tnew Thread(()-{System.out.println(hello t);});t.start();System.out.println(hello main);}
} 上述代码中,先输出hello main 还是先输出hello t是无法确定的,大概率先输出hello main.必定创建线程是需要开销的,但是我们海狮无法确定优先顺序,这就引出一个问题,当我们需要一个场景就是,必须等待线程2执行完了再执行线程1,这时候我们怎么办呢?
使用关键字 join
public class ThreadDemo9 {public static void main(String[] args) throws InterruptedException {Thread thread new Thread(()-{System.out.println(hello t);});thread.start();System.out.println(hello main1);//在main线程中调用thread.join,main线程等待Thread线程,等Thread执行完了之后,在继续执行main线程.thread.join();System.out.println(hello main2);}
} 上述代码的意思是,在主线程中加了一个t.join,就是等待t线程结束之后,再执行t.join之后的main线程中的代码.也就是在t线程结束之前,main线程处于一个堵塞的状态,暂时不参加CPU的调度执行.运行结果如下: 补充: join还有一个版本可以填写一个参数作为“超时时间”等待的最大时间。 join的无参数版本效果就是“死等”不见不散。 join的有参数版本则是执行最大超时时间如果等待的时间到了上限还没有等到咱就不等了。 那么此时就会联想到一个问题,会不会出现两个线程互相等待的情况. 答案:是会出现的 那种情况称为死锁是bug。 比如家钥匙锁车里了车钥匙锁家里了。