书接上回讲到创建线程的五大方法讲了通过Thread与Runnable创建子类来创建线程接下来我们继续。3.使用带有Thread的匿名内部类这个匿名内部类做了三件事第一创建了一个Thread的子类第二在大括号里面就是编写子类的定义代码第三创建了这个匿名内部类的实例并且把实例的引用赋值给t。下图是使用了匿名内部类与原来的代码的对比不难发现这样写就少定义了一些类一般在某个代码是一次性时就可以使用匿名内部类的写法。4.使用带有Runnable的匿名内部类这个的逻辑与Thread的匿名内部类是一样的只是拥有解耦合的作用降低耦合就是为了后来方便对代码的修改使用了Runnable之后任务和线程概念是分离的。5.引入lambda表达式这个本质上是一个回调函数。回调函数就是一个方法的调用需要依靠其他的方法来实现自己不能调用自己。在Java中方法必须要依托于类来存在即“函数式接口”而这个lambda表达式创建了一个匿名的函数式接口的子类并且创建出对应的实例重写了里面的方法因此不用再override重写run方法十分简便。Thread类的其他属性与方法1.Thread()——创建线程对象2.Thread(Runnable) 使用Runnable对象创建线程对象前两个的区别之前已经提过但注意第一个写法必须要重写Thread的run方法而第二种则不必。自己追踪正在运行的线程除了在IDEA编译器中设置线程我们可以在哪里看到正在运行的线程呢还有这些线程的内部是什么样的接下来我们对下图中的这些线程进行追踪这里有t1、t2、t3三个线程接下来我们找到下载JDK的位置按以下几个步骤1.运行IDEA注意不要停止运行最好弄一个加载速度较慢的死循环2.点击IDEA左上角的“File”按钮点击“Project Structure”再点击SDK来查询自己安装的位置3.找到这一文件从JDK-17的bin文件中找到这个文件点进去4.点击正在运行的Demo6并连接进去之前点击“不安全的连接”即可。5.点击“线程”发现自己创建的线程不知为什么我这个突然变成了Thread-0、Thread-1、Thread-2不过这个可以自己命名的这样就可以看到线程的状况。当然这个后面我们还会再提到的。Thread的几个常见属性前四个比较好理解就不过多赘述我们从“是否后台线程”开始。1.是否后台线程——isDaemon()Daemon意为“守护”守护线程就是后台线程后台线程是不影响进程结束的线程反之前台线程影响进程的结束当所有的前台线程都结束了进程才算结束如图下代码本来循环三次打印了“main结束”后就结束进程但是在打印了“main结束”后仍然执行着main方法因此并没有结束进程。但当加上了setDaemon()之后进程就结束了这个setDaemon是设置后台线程影响了后面的start把Thread改为了后台线程因此不妨碍进程的结束。或者这样也可以就像一个酒桌上吃饭一样有有地位的人他们共同决定酒席是否结束也有没地位的人他们不影响酒席。2.是否存活isAlive()Java中创建的Thread对象和系统中的线程是一一对应的关系。但是Thread对象的生命周期和系统中的线程的生命周期是不同的也就是说可能存在Thread对象还存活但是系统中的线程已经销毁的情况。如图除了在start之前的那个为false以外在执行三次循环的情况下竟然出现了四次true这个代码的逻辑3s之后就结束了系统中的入口方法里的逻辑结束了系统中对应的线程也随之销毁了其实打印三个还是四个true都是不确定的由于随机调度主线程第四次打印和t线程的结束先后顺序是不一定的在图中的情况第四个true表明t线程没有完全结束直到后面的false时才结束。3.是否被中断——isInterrupted()这里是判断进程是否中断的方法。创建一个线程——start这个在第一个多线程博客里有不再赘述。但值得一提的是每个Thread对象只能有一次start方法每次想用start创建一个线程都需要创建一个新的Thread对象不能重复利用。中断一个线程——isFinished中断了一个线程就会让线程直接停止不会再恢复。它让一个线程能够结束让线程的入口方法执行完毕后线程就随之结束了。上图中的isFinished是成员变量可以中断、结束线程。可如果是局部变量时可以吗答案是不行的这里涉及到了“变量捕获”这一概念。变量捕获lambda里的!isfinished希望使用外面的、main方法里的变量就触发了“变量捕获”lambda是回调函数它会在很久之后也就是操作系统真正创建出线程之后才会执行这里很有可能后续线程创建好了当前main这里的方法都执行完了对应的局部变量isFinished就销毁了根本用不上。为了解决上述问题Java的做法是把被捕获的变量拷贝一份拷贝给lambda里面这样外面的变量是否销毁就不影响lambda里面的执行了。如果是成员变量时就不再是“变量捕获”这一语法而是“内部类访问外部类的成员”语法。lambda本质上是函数式接口相当于一个内部类isFinished变量本身是外部类的成员。内部类本来就能访问外部类的成员成员变量生命周期也是让GC垃圾回收来管理的在lambda里面不担心变量生命周期失效的问题也就不必拷贝不必限制final之类的。线程终止——Thread.currentThread.isInterrupted()这里不能用t对象来调用isInterrupted方法而标题上的那个是静态方法哪个线程中调用获取到的是哪个线程的Thread引用。当然标题上的语法是为了判断线程是否被终止了而主动进行终止的语法是对象.interrupted();后续再会。我的gitee链接https://gitee.com/QQ2240635095/java41.git