1.线程的创建
1.继承Thread类,重写run方法
2.实现Runnable接口
3.使用匿名内部类继承Thread
4.使用匿名内部类实现Runnable接口
5.使用Lambda表达式
这里需要注意一个细节,那就是使用Lambda表达式的前提条件:
我们所要是实现的接口必须是一个函数式接口
那什么又是函数式接口呢?:接口中有且只有一个抽象方法的接口,当然也可以存在静态方法和默认方法
6.Lambda表达式的变量捕获机制
在下面的代码中,我们想要打印i时,发现报了错,这是为什么呢?
原因就存在我们的Lambda表达式(匿名类)的变量捕获当中,其 规则是表达式中捕获的 变量必须是由final修饰过的,或者保证在使用之前没有发生改变,才能使用
2.线程的中断
1.自己设置标志位
设置一个全局静态变量flag,总线程可以通过设置其值来控制线程是否结束
2.使用Thread自带的标志位
这里的异常报出的原因是:当线程处于sleep休眠状态时,如果这时将其中断,会报出异 常,也就是t.interrupt()会做两件事:1.将线程内部的属性(boolean)设置为true 2.如果此时线程处于休眠状态,那么会唤醒线程且将标志位重新赋值为false,这也就是为什么报异常之后程序并没有结束,还是一直进行下去
3.线程的等待
1. join()
无参数的版本表示:会一直等到线程运行完,也就是
带有一个参数的版本表示:最长会等long millis(毫秒)时间,如果线程还没有运行完,就不会等了
带有两个参数的版本与一个参数的版本一样,只是可以多等额外时间nanos(纳秒)
2.join方法的作用
可以决定两个线程之间的执行顺序
线程1先执行
线程2先执行
4.线程的休眠
1.sleep
操作系统内核层面:
内核中是通过pcb来感知线程存在的,一个一个pcb我们可以简单地理解为由链表串起来的,当线程休眠时,对应的pcb会退出当时链表,回到阻塞队列中,不参与cpu的调度,当休眠时间到达了的时候,再 重新返回调度队列,但不会立马返回,所以如果sleep1000ms,其时间间隔是要大于1000ms
5.获取线程实例
Thread的几个常见属性:
1.ID:getID()
2.名称:getName() : 构造方法中起的名字
3.状态:getState()
4.优先级:getPirority()
5.是否为后台线程:isDaemon()
6.是否被中断:isInterrupted()
7.是否存活:isAlive()