参考文章
如果一个类继承 Thread类,则不适合于多个线程共享资源,而实现了 Runnable 接口,就可以方便的实现资源的共享。
在此提出一个问题,Java 程序每次运行至少启动几个线程?
回答:至少启动两个线程,每当使用 Java 命令执行一个类时,实际上都会启动一个 JVM,每一个JVM实际上就是在操作系统中启动一个线程,Java 本身具备了垃圾的收集机制。所以在 Java 运行时至少会启动两个线程,一个是 main 线程,另外一个是垃圾收集线程。
Java中实现多线程的两种方式:
- 实现Runnable接口
- 继承Thread类
线程的五种状态:创建,就绪,运行,阻塞,死亡
创建 Thread t=new Thread();
就绪 t.start(); 进入线程队列
运行 run()
阻塞 Thread.sleep() ,suspend(),wait()或因为耗时的输入/输出而被cpu中止执行,进入阻塞状态。在阻塞原因消除后回到线程队列中就绪
死亡 线程执行结束或调用stop()
同步
⭐⭐ synchronized 内置锁 修饰方法/语句块 阻塞同步
高开销 ???
⭐ java.util.concurrent.ReentrantLock 阻塞同步
步骤: 1. Lock lock=new ReentrantLock();
2. lock.lock();
3.finally{ lock.unlock(); }
锁的劣势:死锁,优先级反转
|
|
CAS模式
|
|
原子变量类 (非阻塞同步)
static的特点:
1.static是一个修饰符,用于修饰成员;
2.static修饰的成员被所有的对象所共享;
3.static优先于对象存在,因为static的成员随着类的加载就已经存在了;
4.static修饰的成员多了一种调用方式,就可以直接被类名所调用。(类名.静态成员)
5.static修饰的数据是共享数据,对象中存储的是特有数据
原子操作类AtomicInteger
使用原子变量类(例如AtomicInteger和AtomicReference)来构建高效的非阻塞算法,原子变量类比锁的粒度更细量级更轻,将发生竞争的范围缩小到单个变量上。使用原子变量类(例如AtomicInteger和AtomicReference)来构建高效的非阻塞算法,原子变量类比锁的粒度更细量级更轻,将发生竞争的范围缩小到单个变量上
java.util.concurrent.atomic 类的小工具包,支持在单个变量上解除锁的线程安全编程。
AtomicBoolean 可以用原子方式更新的 boolean 值。
AtomicInteger 可以用原子方式更新的 int 值。
AtomicIntegerArray 可以用原子方式更新其元素的 int 数组。
AtomicIntegerFieldUpdater<T> 基于反射的实用工具,可以对指定类的指定 volatile int 字段进行原子更新。
AtomicLong 可以用原子方式更新的 long 值。
AtomicLongArray 可以用原子方式更新其元素的 long 数组。
AtomicLongFieldUpdater<T> 基于反射的实用工具,可以对指定类的指定 volatile long 字段进行原子更新。
AtomicMarkableReference<V> AtomicMarkableReference 维护带有标记位的对象引用,可以原子方式对其进行更新。
AtomicReference<V> 可以用原子方式更新的对象引用。
AtomicReferenceArray<E> 可以用原子方式更新其元素的对象引用数组。
AtomicReferenceFieldUpdater<T,V> 基于反射的实用工具,可以对指定类的指定 volatile 字段进行原子更新。
AtomicStampedReference<V> AtomicStampedReference 维护带有整数“标志”的对象引用,可以用原子方式对其进行更新。