进程和线程
Java的多线模型JMM问题可以总结为 2 个核心,3个要点
2个核心:主内存,工作内存缓冲区 重点 主内存和 工作内存缓冲区的数据不一致问题,原因是工作内存缓冲区是线程私有的,数据更新后,同步到主内存有时间差,而另外一个原因重排序,编译器会对指令进行优化重拍。
3个要点:原子性,可见性,有序性(happen-before) happen-before原则保证了某些指令必须在前面或者后面,指令重排有限制。
进程是计算机分配内存资源的基本单位,它是程序的一次运行的结果。
线程是进程的子集,线程是计算机调度的基本单位,进程内通过调度不同的线程执行不同的任务,线程共同分享进程的内存资源。
Java线程的状态,
wait,sleep,join,等方法会让线程进入等待状态或者超时等待状态
线程的阻塞状态,由线程的等待,超时等待,等待通知,IO请求,等待锁等引起的。
Java的锁
Java使用类的对象头,栈帧的锁记录 即为实现锁机制。
对象头拥有 锁状态,hashcode,年龄标记,偏向锁 字段
Java中使用多线程的方式
继承Thread类,实现run方法
实现Runner接口,实现run方法
实现Callable接口,实现call方法,返回值是一个Future接口,Future接口可以控制线程的活动状态和取得方法结果
start方法会在当前线程内创建一个新的线程,run方法是线程执行的方法体,如果在当前线程内调用run,不会启动一个新的线程。
线程的常用方法
isAlive()
sleep()
getId()
Thread.currentThread()
疑难点:线程的中断
中断方法this.interrupt() 将线程的打上中断标识,但是线程并不会停止
this.interrupted 静态方法,判断当前线程是否中断,副作用是把线程的中断标识抹去
this.isInterrupted 判断线程是否中断,没有副作用
疑难点: 线程如何停止
常用的方法是用 没有副作用的中断方法 isInterrupted判断 后,如果为真,那么抛出一个中断异常 throw new InterruptedException();
当然也可以采用 return ; 的方式 让线程停止,但是不推荐这种方式,因为用异常的方式,可以将异常抛出给上一层捕捉,代码的体验更好。
在sleep后,执行线程的中断方法interrupt()
在sleep状态下,停止某一个线程会抛出中断异常,并清除中断标识
被忽略的方法 yield 方法
这个方法的作用是让正在执行的线程放弃CPU资源,让给其他的线程。但是线程的执行是不可预知的,有可能刚刚放弃CPU,马上又获得了CPU。
守护线程
setDaemon
对象和变量的并发访问
并发:多个线程在一段时间间隔内对共享临界资源的访问,这个可能导致脏读。如果一个线程在读取一个数据量,而另外的一个线程同时在修改这个数据量,这就会导致当前线程读取的数据是修改前的,不是最新的。
解决的办法就是 同步,但是在同步之前,需要知道一点,那就是只有对共一个资源的访问 才会导致多线程的 竞争,而在Java中 的临界资源可以是 一个相同的变量,一个相同的引用对象,一个相同的引用对象的方法,等。
Java中锁的相关概念:
每一个实例对象都