线程状态
概述:
当线程被创建并启动以后,它既不是⼀启动就进⼊了执⾏状态,也不是⼀直处于执⾏状态。在线程的⽣命周期中,有⼏种状态呢?在API 中 java.lang.Thread.State 这个枚举中给出了六种线程状态 :- NEW(新建):线程刚被创建,但是并未启动。还没调用start方法。MyThread t = new,MyThread()只有线程对象,没有线程特征。创建线程对象时
- Runnable(可运行):线程可以在java虚拟机中运行的状态,可能正在运行自己的代码,也可能没有,这取决于操作系统处理器,调用start()方法:就绪。调用start方法时
- Blocked(锁阻塞):当⼀个线程试图获取⼀个对象锁,⽽该对象锁被其他的线程持有,则该线程进⼊Blocked状态;当该线程持有锁时,该线程将变成Runnable状态。等待锁对象时
- Waiting(⽆限等待):⼀个线程在等待另⼀个线程执⾏⼀个(唤醒)动作时,该线程进⼊Waiting状态。进⼊这个状态后是不能⾃动唤醒的,必须等待另⼀个线程调⽤notify或者notifyAll⽅法才能够唤醒。调⽤wait()⽅法时
- Timed Waiting(计时等待):同waiting状态,有⼏个⽅法有超时参数,调⽤他们将进⼊Timed Waiting状 态。这⼀状态将⼀直保持到超时期满或者接收到唤醒通知。带有超时参数的常⽤⽅法有Thread.sleep 、Object.wait。调⽤sleep()⽅法时
- Teminated(被终止): 因为run⽅法正常退出⽽死亡,或者因为没有捕获的异常终⽌了run⽅法⽽死亡。run⽅法执⾏结束时,或者执⾏任务的时候出现了异常,但没有try处理
等待唤醒机制
什么是等待唤醒机制?
这是多个线程间的⼀种协作机制。就好⽐在公司⾥你和你的同事们,你们可能存在在晋升时的竞争,但更多时候你们更多是⼀起合作以完成某些任务。就是在⼀个线程进⾏了规定操作后,就进⼊⽆限等待状态(wait()),调⽤notfiy()⽅法唤醒其他线程来执⾏,其他线程执⾏完后,进⼊⽆限等待,唤醒等待线程执⾏,依次类推.... 如果需要,可以使⽤ notifyAll()来唤醒所有的等待线程wait/notify 就是线程间的⼀种协作机制。
等待唤醒机制相关方法介绍
- public void wait():让当前线程进入等待状态此方法必须锁对象调用
- public void notify():唤醒当前锁对象上等待状态的线程此方法必须锁对象调用
代码:
public class Test {
static Object obj = new Object();
public static void main(String[] args) {
// 步骤1 : ⼦线程开启,进⼊⽆限等待状态, 没有被唤醒,⽆法继续运⾏.
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("准备进⼊⽆限等待状态...");
synchronized (obj){
try {
obj.wait();
} catch
(InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
}
}
经典案例:
public class CK {
boolean flag = false;//仓库默认false,表示没有东西
String xianer;
}
public class XFz implements Runnable{
CK ck;
public XFz(CK ck){
this.ck = ck;
}
@Override
public void run() {
while (true) {
synchronized (ck){
if (ck.flag==true) {
System.out.println("吃货正在吃"+ck.xianer+"包子");
ck.flag = false;//表示吃完了
ck.notify();
System.out.println("吃完啦!");
}
if (ck.flag==false) {
System.out.println("由于没有包子,所以准备进入等待");
try {
ck.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
}
public class SCZ implements Runnable {
CK ck;
public SCZ(CK ck) {
this.ck = ck;
}
@Override
public void run() {
while (true) {
synchronized (ck) {
if (ck.flag==true) {
System.out.println("有包子,所以准备进入等待");
try {
ck.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
if (ck.flag==false) {
ck.xianer = "猪肉大葱";
ck.flag = true;
ck.notify();
System.out.println("包好了");
}
}
}
}
}
public class ceshi {
public static void main(String[] args) {
CK ck = new CK();
new Thread(new SCZ(ck)).start();
new Thread(new XFz(ck)).start();
}
}
Lambda表达式
面向对象编程思想:
⾯向对象强调的是对象 , “必须通过对象的形式来做事情”,相对来讲⽐较复杂,有时候我们只是为了做某件事情⽽不得不创建⼀个对象 , 例如线程执⾏任务,我们不得不创建⼀个实现Runnable接⼝对象,但我们真正希望的是将run⽅法中的代码传递给线程对象执⾏
函数编程思想:
在数学中,函数就是有输⼊量、输出量的⼀套计算⽅案,也就是“拿什么东⻄做什么事情”。相对⽽⾔,⾯向对象过分强调“必须通过对象的形式来做事情”,⽽函数式思想则尽量忽略⾯向对象的复杂语法——强调做什么,⽽不是以什么形式做。例如线程执⾏任务 , 使⽤函数式思想 , 我们就可以通过传递⼀段任务代码给线程对象执行,而不需要创建任务对象
实现 Runnable 接口的⽅式创建线程执行任务
public class MyRunnable implements Runnable {
@Override
public void run() {
System.out.println("实现的⽅法创建线程的任务执⾏了...");
}
}
public class Demo {
public static void main(String[] args) {
// 实现类的⽅式:
MyRunnable mr = new MyRunnable();
Thread t = new Thread(mr);
t.start();
}
}
匿名内部类⽅式创建线程执行任务
public class Demo {
public static void main(String[] args) {
// 匿名内部类的⽅式:
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("匿名内部类的⽅式创建线程的任务执⾏了");
}
});
t2.start();
}
}
Lambda方
式创建线程执行任务
以上
2
种⽅式都是通过
Runnable
接⼝的实现类对象
,
来传⼊线程需要执⾏的任务(
⾯向对象编程
)
思考
:
是否能够不通过
Runnable
接⼝的实现类对象来传⼊任务,
⽽是直接把任务传给线程
????
Lambda
表达式的概述
:
它是⼀个
JDK8
开始⼀个新语法。它是⼀种
“
代替语法
”——
可以代替我们之前编写的“
⾯向某种接⼝
”
编程的情况
public class Demo01 {
public static void main(String[] args) {
// 体验Lambda表达式的⽅式:
Thread t1 = new Thread(()->{
System.out.println("Lambda表达式的方式");//Lambda表达式的作⽤就是简化代码,省略了⾯向对象中类和⽅法的书写。
});
t1.start();
}
}
Lambda 省去⾯向对象的条条框框,格式由 3 个部分 组成:Lambda表达式的格式
- 一些参数
- 一个箭头
- 一段代码
Lambda表达式的标准格式为:
( 参数类型 参数名称 ) -> { 代码语句 }
格式说明
- ⼩括号内的语法与传统⽅法参数列表⼀致:⽆参数则留空;多个参数则⽤逗号分隔。
- ->是新引⼊的语法格式,代表指向动作。
- ⼤括号内的语法与传统⽅法体要求基本⼀致
比较器案例:
public class Demo02 {
public static void main(String[] args) {
//比较器案例
List list = new ArrayList<>();
Collections.addAll(list,1,2,6,9,5);
System.out.println("排序之前的集合"+list);
Collections.sort(list,new Comparator() {
public int compare(Integer o1, Integer o2) {
return o2-o1;
}
});
System.out.println("排序之后的集合"+list);
//函数式编程思想 Lambda表达式
Collections.sort(list, (Integer o1,Integer o2)->{return o2-o1;});
System.out.println("使用Lambda排序之后的集合"+list);
}
}
省略规则
在Lambda标准格式的基础上,使用省略写法的规则为:
- 小括号内参数的类型可以省略;
- 如果小括号内有且仅有⼀个参数,则小括号可以省略;
- 如果大括号内 有且仅有⼀条语句 ,则⽆论是否有返回值,都可以省略大括号、return 关键字及语句分号。
public class Demo_⽐较器演示 {
public static void main(String[] args) {
//⽐较器
ArrayList list = newArrayList<>();
//添加元素
list.add(324);
list.add(123);
list.add(67);
list.add(987);
list.add(5);
System.out.println(list);
//Lambda表达式
Collections.sort(list, ( o1, o2)->o2 - o1);
//打印集合
System.out.println(list);
}
}



