Thread初始化过程

1.创建你的线程就是你的父线程

2.如果没有指定threadgroup,你的threadgroup就是父线程的threadgroup

3.如果没有指定daemon,你的daemon状态默认是父线程的daemon。

/**

  • 只要设置了这个标志位,就代表这个线程是daemon线程,后台线程
  • 非daemon,我们一般叫工作线程
  • 如果工作线程(main线程)都结束了,daemon线程不会阻止jvm进程退出的
  • daemon线程会跟着jvm线程一起退出

  • */

  1. 你的优先级默认是父线程的优先级
  2. 如果没有指定线程名称,那么默认是thread-0格式的名称
  3. 线程id是全局递增的,从1开始

thread的启动过程

  1. 一旦启动了线程, 就不能再重新启动了,多次调用start方法。因为启动了之后,threadStatus就是非0的状态,此刻就不能重新调用了
  2. 你启动线程之后,这个线程就会加入之前处理好的那个线程组肿
  3. 启动一个线程实际上走的是native方法,start0(),会实际的启动一个线程
  4. 一个线程启动之后会执行run()方法

join方法

1.main线程里面开启了一个线程,main线程如果对那个线程调用了join方法,那么就会导致main线程会阻塞住,他会等其他线程的代码执行结束,那个线程执行完毕,
然后main线程才会继续往下走

interrupt

interrupt,可以中断一个线程,标志位为false,isInterrupted()方法判断;
打断一个线程的休眠
在分布式系统中一半用来实现优雅退出

volatile

并发编程中,一个线程修改了变量的值,其他线程立马可以感知到。

cpu的底层缓存会导致并发问题。导致数据不一致
MESI协议,保证在cpu缓存模型下,不会出现多线程并发读写变量,没办法及时感知到

java内存模型


分为工作内存和主内存

read(从主内存中读取)

load(将主内存读取到的值写入工作内存)

use(从工作内存读取数据来计算)

assign(将计算好的值重新赋值到工作内存中)

store(将工作内存数据写入主存)

writ(将store过去的变量值赋值给主存的变量
)
image.png

并发变成的三个特性:可见性,原子性,有序性

  1. 可见性

上面说的就是并发的可见性问题,线程1修改的东西,对线程2是不可见的

  1. 原子性

以i++举例,对于i++的操作,只要多个线程并发运行来执行代码,不能保证原子性,如果保证原子性,
第一个线程i++,i=1.第二个线程,i++,i=2.

  1. 有序性

对于代码,同时还有一个问题是指令重排序,编译器和指令器。有时候为了提高效率,会将指令重排序,但是有时候会导致一些问题