一、💛
Java的Thread类表示线程
1.创建类,继承Thread重写run方法
2.创建类,实现Runnable重写run方法
3.可以继承Thread重写run基于匿名内部类
4.实现Runnable重写run基于匿名内部类
5.lamdba表达式表示run方法的内容(推荐)
6。基于Callable(以后学)
7.基于线程池(以后学)
匿名内部类(不用看定义,看下面用法领悟):正常建类后面大括号,这一步相当于先创建一个子类,但是这个子类是没有名字(匿名),另一方面,这类的创建是在Demo这个类里面。
下面这个写法是3号💛💛
我们要记住一个是,最重要的是写run这个是赋予了线程需要做什么工作。
public class Demo { public static void main(String[] args) throws InterruptedException { Thread t=new Thread(){ //匿名内部类,看上面详细解答 @Override public void run() { //子类中重写了run方法,实现了线程要干的工作 while(true){ System.out.println("hello world"); try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } } } }; t.start(); //创建了该类的实例,并且是使用那个t这个引用指向。 while (true) { System.out.println("love"); Thread.sleep(1000); } } }
写法4😃😃
为什么括号不是封死的,因为小括号对应的是Thread构造方法的结束,new Runnable整个一段,都在构造出一个Thread的参数, 创建这个匿名内部类,通过构造方法传给Thread。
public class Demo { public static void main(String[] args) throws InterruptedException { Thread t=new Thread(new Runnable (){ //!!!括号不是封死的 @Override public void run() { while(true){ System.out.println("hello world"); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } } ) ; //!!!!!看这个小括号 t.start(); while (true) { System.out.println("love"); Thread.sleep(1000); } } }
5.使用lambda(推荐的方法) 表示run方法的内容😗😗 (本质是匿名方法,这样的匿名函数,主要可以作为回调函数使用。——回调函数(合适的时候就干,不合适就选择不干。),不需要程序猿们主动去调动(需要知道函数名,才能被调动,常用场景 1.服务器开发 2.图形界面开发,用户的某个操作,触发回调),而是在合适的时机自动的被调动
Java本身不允许函数脱离类,但是lambda特例,起名叫“函数式接口”(😊必须只有一个方法😊)
类似于Lammbda这样的写法,本质上并没有新增新的语言特性,而是把以往实现的功能,换了一种更简单的方式编写。
public class Demo { public static void main(String[] args) throws InterruptedException { Thread t=new Thread(()->{ //也是没有右括号,在下面。 while(true){ System.out.println("hello world"); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } }); t.start(); while (true) { System.out.println("love"); Thread.sleep(1000); } } }
二、 💚
Thread就是Java,线程的代言人,系统中一个线程,对应Java中一个Thread对象
public class Demo { public static void main(String[] args) throws InterruptedException { Thread t=new Thread(()->{ while(true){ System.out.println("hello world"); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } },"myThread"); //给这个进程起名字 t.start(); while (true) { System.out.println("love"); Thread.sleep(1000); } } }
Thread常见ID。线程的身份标识(JVM,给设定了一个标识)
一个线程可以存好几个身份标记:
1.JVM有一个身份标记
2.pthread库(系统给程序猿提供的操作线程的API,也有一个线程的身份标识)
3.内核里面,针对线程的PCB还有身份标识
Thread常见属性
id. getId()
name. getname()
状态。 getState() java中线程的状态和操作系统的有一定差异。
优先级 getPriority 设置获取优先级的作用不是很大,线程的调度,主要还是系统内核负责~系统的调度速度更快。
是否是后台进程 isDaemon()
后台进程/守护进程,后台进程不影响进程结束,(创建的线程默认是前端线程)前台进程会影响到进程结束,如果前台进程没执行完,进程是不会结束的。
一个进程的所有前台线程,都执行完退出了,那么即使存在后端线程没有执行完毕,也会随着进程一起退出
setDaemon(true) 把某一个进程,设置为后端进程,这样前端线程结束,后面的也结束了
public class Demo { public static void main(String[] args) throws InterruptedException { int n =0; Thread t=new Thread(()->{ int m =0; while(m<9){ System.out.println("hello world"); m++; try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } },"myThread"); t.setDaemon(true); //设置为后端线程 t.start(); while (n<3) { // 打印完事走完全部就结束了,所以一定会有这三个 System.out.println("love"); n++; Thread.sleep(1000); } } }
是否存活 isAlive
Thread对象,对应的线程(在系统内核中)是否存活。
Thread对象,并不是和系统中的线程完全一样(同生共死)的。
一般的Thread对象,先创建好,~手动调用start ,内核才真正创造出线程
消亡的时候,
可能对象,先结束了生命周期(没有引用指向这个对象)
也有可能Thread对象还在,内核中的线程把run执行完成了,就结束了。
对象的整个生命周期大致可以分为7个阶段:
创建阶段、应用阶段、不可视阶段、不可到达阶段、可收集阶段、终结阶段、与释放阶段(了解就好)
重要方法start():真正创造出线程->调用系统API完成线程创建工作(本身是一瞬间完成的,相当于是传话的小弟,“你造个线程出来😈”,调用API之后代码立刻执行start之后的逻辑
操作系统=内核+配套的程序
一个系统最核心的功能:
1.对下管理好各种硬件设备
2.对上,给各种程序提供稳定的运行环境
操作系统的内核(应用程序):
创建线程,非常核心的功能,系统API,系统调用
一般情况应用,不可进入内核操作,不可进入内核的程序成为“用户态”
如果一些应用程序,能够进入后台,直接操作内核里面的一些数据结构,程序是出于“内核态”这样的程序还叫做驱动程序