线程基础

2019-03-11  本文已影响0人  林亚希

概念

运行程序会创建一个进程。但OS调度的最小单元是线程(轻量级进程)。
普通的java程序包含的线程:

为什么要用线程?

  1. 充分利用多处理核心;
  2. 更快的响应时间(用户订单的场景,发送邮件等部分可由其他线程执行)

启动线程和退出线程

创建线程的方法

extends Thread
implements Runnable
启动线程:threadl类的start()
线程完成:1、run()方法执行完成;2、抛出一个未处理的异常导致线程的提前结束

取消和中断

处理不可中断的阻塞

线程的状态

新创建 线程被创建,但是没有调用start方法
可运行(RUNNABLE) 运行状态,由cpu决定是不是正在运行
被阻塞(BLOCKING) 阻塞,线程被阻塞于锁
等待/计时等待(WAITING) 等待某些条件成熟
被终止 线程执行完毕

线程的优先级

成员变量priority控制优先级,范围1-10之间,数字越高优先级越高,缺省为5,创建线程时setPriotity()可以设置优先级,不要指望他发挥作用。

Daemon线程

守护型线程(如GC线程),程序里没有非Daemon线程时,java程序就会退出。一般用不上,也不建议我们平时开发时使用,因为Try/Finally里的代码不一定执行的。

常用方法深入理解

volatile和synchronized

多个线程同时访问一个共享的变量的时候,每个线程的工作内存有这个变量的一个拷贝,变量本身还是保存在共享内存中。
Violate修饰字段,对这个变量的访问必须要从共享内存刷新一次。最新的修改写回共享内存。可以保证字段的可见性。绝对不是线程安全的,没有操作的原子性。
适用场景:1、一个线程写,多个线程读;2、volatile变量的变化很固定
关键字synchronized可以修饰方法或者以同步块的形式来进行使用,它主要确保多个线程在同一个时刻,只能有一个线程处于方法或者同步块中,它保证了线程对变量访问的可见性和排他性,又称为内置锁机制。
Synchronized的类锁和对象锁,本质上是两把锁,类锁实际锁的是每一个类的class对象。对象锁锁的是当前对象实例。

等待和通知机制

等待方原则:
1、获取对象锁
2、如果条件不满足,调用对象的wait方法,被通知后依然要检查条件是否满足
3、条件满足以后,才能执行相关的业务逻辑
Synchronized(对象){
While(条件不满足){
对象.wait()
}
业务逻辑处理
}
通知方原则:
1、获得对象的锁;
2、改变条件;
3、通知所有等待在对象的线程
Synchronized(对象){
业务逻辑处理,改变条件
对象.notify/notifyAll
}

join方法

线程A,执行了thread.join(),线程A等待thread线程终止了以后,A在join后面的语句才会继续执行

ThreadLocal

本质是个map,map的键就是每个线程对象,值就是每个线程所拥有的值
常用方法:
initialValue()
get()
set()
remove():将当前线程局部变量的值删除,这个方法是JDK 5.0新增的方法。当线程结束后,对应该线程的局部变量将自动被垃圾回收,所以显式调用该方法清除线程的局部变量并不是必须的操作,但它可以加快内存回收的速度。
ThreadLocal拥有的这个变量,在线程之间很独立的,相互之间没有联系。内存占用相对来说比较大。

性能问题

串行化、无锁化、异步化编程是趋势之一,比如node.js,Vert.x。
黄金原则:编码时候不要考虑性能优化的事情,先正确实现业务,发现性能不行,这个时候再来考虑性能优化。

上一篇 下一篇

猜你喜欢

热点阅读