常见的一般是4种:
- 继承Thread类
- 实现Runnable接口
- 通过callable接口,实现有返回值的线程
- 基于线程池的实现
虽说有四种,但究其根本,其实都是实现的Runnable接口
操作系统层面:就传统的线程状态来说有5种状态
新建(new)、就绪(ready)、运行(running)、等待(waiting)、结束(terminated)
java中有6种状态
新建、就绪/运行、阻塞、等待、时间等待、结束
有两种方法:第一种是使用interrupt方式,也是比较推荐的方式
Thread.currentThread().interrupt()
执行该方法之后,线程并不会马上停止,而是将一个中断标记位设置为了true,由线程自己停止
第二种:使用全局变量的方式。
static volatile boolean flag = true;
public static void main(String[] args) throws InterruptedException{
Thread t1 = new Thread(()->{
while(flag){
//处理任务
}
System.out.println("任务结束");
});
t1.start();
Thread.sleep(500);
flag = false;
}
sleep方法不需要别人唤醒,设置睡眠时间之后,自己醒来,继续执行,同时不会释放锁
wait方法需要别人唤醒,比如notify或者notifyAll方法,同时会释放锁
wait方法和sleep方法所在的类不同,wait方法在object类,sleep方法是Thread类中的static方法
原子性、可见性、有序性
原子性的定义:原子性指一个操作是不可分割的,不可中断的,一个线程在执行时,另一个线程不会影响到它。
可见性:多核CPU的三级缓存都是独立的,只改自己的工作内存,没及时同步到主内存,导致数据不一致问题。
有序性:java文件在编译时,为了提升执行效率,对指令进行重排。(为了尽可能的发挥CPU的性能)
volatile可以解决可见性、有序性的问题,但并不能解决原子性问题