1.多线程
是指从软件或者硬件上实现多个线程并发执行的技术。 具有多线程能力的计算机因有硬件支持而能够在同一时间执行多个线程,提升性能。
并发 在同一时刻,有多个指令在单个CPU上交替执行。 并行 在同一时刻 ,有多个指令在多个CPU上同时执行。
进程 是正在运行的程序 线程 是进程中的单个顺序控制流,是一条执行路径 单线程: 一个进程如果只有一条执行路径,则称为单线程程序 多线程: 一个进程如果有多条执行路径,则称为多线程程序
实现方法 继承Thread类 实现Runnable接口 实现Callable接口
实现方法-继承Thread类-加static
方法名 说明 区别 void run() 在线程开启后,此方法将被调用执行(要重写run()方法,因为run()是用来封装被线程执行的代码) 封装线程执行的代码,直接调用,相当于普通方法的调用 void start() 使此线程开始执行,Java虚拟机会调用run方法() 启动线程;然后由JVM调用此线程的run()方法
public class MyThread extends Thread {
@Override
public void run ( ) {
for ( int i= 0 ; i< 100 ; i++ ) {
System . out. println ( i) ;
}
}
}
public class MyThreadDemo {
public static void main ( String [ ] args) {
MyThread my1 = new MyThread ( ) ;
MyThread my2 = new MyThread ( ) ;
my1. start ( ) ;
my2. start ( ) ;
}
}
实现方法-实现Runnable接口
方法名 说明 Thread(Runnable target) 分配一个新的Thread对象 Thread(Runnable target, String name) 分配一个新的Thread对象
public class MyRunnable implements Runnable {
@Override
public void run ( ) {
for ( int i= 0 ; i< 100 ; i++ ) {
System . out. println ( Thread . currentThread ( ) . getName ( ) + ":" + i) ;
}
}
}
public class MyRunnableDemo {
public static void main ( String [ ] args) {
MyRunnable my = new MyRunnable ( ) ;
Thread t1 = new Thread ( my, "坦克" ) ;
Thread t2 = new Thread ( my, "飞机" ) ;
t1. start ( ) ;
t2. start ( ) ;
}
}
实现方法-实现Callable接口
方法名 说明 V call() 计算结果,如果无法计算结果,则抛出一个异常 FutureTask(Callable callable) 创建一个 FutureTask,一旦运行就执行给定的 Callable V get() 如有必要,等待计算完成,然后获取其结果
public class MyCallable implements Callable < String > {
@Override
public String call ( ) throws Exception {
for ( int i = 0 ; i < 100 ; i++ ) {
System . out. println ( "跟女孩表白" + i) ;
}
return "答应" ;
}
}
public class Demo {
public static void main ( String [ ] args) throws ExecutionException , InterruptedException {
MyCallable mc = new MyCallable ( ) ;
FutureTask < String > ft = new FutureTask < > ( mc) ;
Thread t1 = new Thread ( ft) ;
String s = ft. get ( ) ;
t1. start ( ) ;
System . out. println ( s) ;
}
}
三种方式的对比
实现Runnable、Callable接口
好处: 扩展性强,实现该接口的同时还可以继承其他的类 缺点: 编程相对复杂,不能直接使用Thread类中的方法 继承Thread类
好处: 编程比较简单,可以直接使用Thread类中的方法 缺点: 可以扩展性较差,不能再继承其他的类
设置和获取线程名称
方法名 说明 void setName(String name) 将此线程的名称更改为等于参数name String getName() 返回此线程的名称 Thread currentThread() 返回对当前正在执行的线程对象的引用
public class MyThread extends Thread {
public MyThread ( ) { }
public MyThread ( String name) {
super ( name) ;
}
@Override
public void run ( ) {
for ( int i = 0 ; i < 100 ; i++ ) {
System . out. println ( getName ( ) + ":" + i) ;
}
}
}
public class MyThreadDemo {
public static void main ( String [ ] args) {
MyThread my1 = new MyThread ( ) ;
MyThread my2 = new MyThread ( ) ;
my1. setName ( "高铁" ) ;
my2. setName ( "飞机" ) ;
MyThread my1 = new MyThread ( "高铁" ) ;
MyThread my2 = new MyThread ( "飞机" ) ;
my1. start ( ) ;
my2. start ( ) ;
System . out. println ( Thread . currentThread ( ) . getName ( ) ) ;
}
}
线程休眠
方法名 说明 static void sleep(long millis) 使当前正在执行的线程停留(暂停执行)指定的毫秒数Thread.sleep(100)
线程优先级
Java使用的是抢占式调度模型:优先让优先级高的线程使用 CPU,如果线程的优先级相同,那么会随机选择一个,优先级高的线程获取的 CPU 时间片相对多一些
方法名 说明 final int getPriority() 返回此线程的优先级 final void setPriority(int newPriority) 更改此线程的优先级线程默认优先级是5;线程优先级的范围是:1-10
public class MyCallable implements Callable < String > {
@Override
public String call ( ) throws Exception {
for ( int i = 0 ; i < 100 ; i++ ) {
System . out. println ( Thread . currentThread ( ) . getName ( ) + "---" + i) ;
}
return "线程执行完毕了" ;
}
}
public class Demo {
public static void main ( String [ ] args) {
MyCallable mc = new MyCallable ( ) ;
FutureTask < String > ft = new FutureTask < > ( mc) ;
Thread t1 = new Thread ( ft) ;
t1. setName ( "飞机" ) ;
t1. setPriority ( 10 ) ;
t1. start ( ) ;
MyCallable mc2 = new MyCallable ( ) ;
FutureTask < String > ft2 = new FutureTask < > ( mc2) ;
Thread t2 = new Thread ( ft2) ;
t2. setName ( "坦克" ) ;
t2. setPriority ( 1 ) ;
t2. start ( ) ;
}
}
守护线程
使用场景:聊天的过程中传输文件,当关闭聊天,则传输文件线程也关闭
方法名 说明 void setDaemon(boolean on) 将此线程标记为守护线程,当运行的线程都是守护线程时,Java虚拟机将退出
守护线程不一定可以执行完,等普通线程执行完之后守护线程就可以结束了,可能会有时延
public class MyThread1 extends Thread {
@Override
public void run ( ) {
for ( int i = 0 ; i < 10 ; i++ ) {
System . out. println ( getName ( ) + "---" + i) ;
}
}
}
public class MyThread2 extends Thread {
@Override
public void run ( ) {
for ( int i = 0 ; i < 100 ; i++ ) {
System . out. println ( getName ( ) + "---" + i) ;
}
}
}
public class Demo {
public static void main ( String [ ] args) {
MyThread1 t1 = new MyThread1 ( ) ;
MyThread2 t2 = new MyThread2 ( ) ;
t1. setName ( "女神" ) ;
t2. setName ( "备胎" ) ;
t2. setDaemon ( true ) ;
t1. start ( ) ;
t2. start ( ) ;
}
}
线程同步
StringBuilder和StringBuffer的区别: StringBuilder和StringBuffer的每一个方法都一样 但是StringBuffer的每一个方法都有synchronized 保证线程同步
同步代码块:
synchronized ( 任意对象) {
多条语句操作共享数据的代码
}
使用场景:某电影院目前正在上映国产大片,共有100张票,而它有3个窗口卖票,请设计一个程序模拟该电影院卖票
public class SellTicket implements Runnable {
private int tickets = 100 ;
private Object obj = new Object ( ) ;
@Override
public void run ( ) {
while ( true ) {
synchronized ( obj) {
if ( tickets > 0 ) {
try {
Thread . sleep ( 100 ) ;
} catch ( InterruptedException e) {
e. printStackTrace ( ) ;
}
System . out. println ( Thread . currentThread ( ) . getName ( ) + "正在出售第" + tickets + "张票" ) ;
tickets-- ;
}
}
}
}
}
public class SellTicketDemo {
public static void main ( String [ ] args) {
SellTicket st = new SellTicket ( ) ;
Thread t1 = new Thread ( st, "窗口1" ) ;
Thread t2 = new Thread ( st, "窗口2" ) ;
Thread t3 = new Thread ( st, "窗口3" ) ;
t1. start ( ) ;
t2. start ( ) ;
t3. start ( ) ;
}
}
同步方法格式
修饰符 synchronized 返回值类型 方法名( 方法参数) {
方法体;
}
特点: 1.同步方法是锁住方法里面所有的代码 2.锁对象不能自己指定 非静态:this 静态:当前类的字节码文件对象(如果是class MyRunnable,那么synchronized(MyRunnable.class))
public class MyRunnable implements Runnable {
private static int ticketCount = 100 ;
@Override
public void run ( ) {
while ( true ) {
if ( "窗口一" . equals ( Thread . currentThread ( ) . getName ( ) ) ) {
boolean result = synchronizedMthod ( ) ;
if ( result) {
break ;
}
}
if ( "窗口二" . equals ( Thread . currentThread ( ) . getName ( ) ) ) {
synchronized ( MyRunnable . class ) {
if ( ticketCount == 0 ) {
break ;
} else {
try {
Thread . sleep ( 10 ) ;
} catch ( InterruptedException e) {
e. printStackTrace ( ) ;
}
ticketCount-- ;
System . out. println ( Thread . currentThread ( ) . getName ( ) + "在卖票,还剩下" + ticketCount + "张票" ) ;
}
}
}
}
}
private static synchronized boolean synchronizedMthod ( ) {
if ( ticketCount == 0 ) {
return true ;
} else {
try {
Thread . sleep ( 10 ) ;
} catch ( InterruptedException e) {
e. printStackTrace ( ) ;
}
ticketCount-- ;
System . out. println ( Thread . currentThread ( ) . getName ( ) + "在卖票,还剩下" + ticketCount + "张票" ) ;
return false ;
}
}
}
public class Demo {
public static void main ( String [ ] args) {
MyRunnable mr = new MyRunnable ( ) ;
Thread t1 = new Thread ( mr) ;
Thread t2 = new Thread ( mr) ;
t1. setName ( "窗口一" ) ;
t2. setName ( "窗口二" ) ;
t1. start ( ) ;
t2. start ( ) ;
}
}
Lock锁
为了更清晰的表达如何加锁和释放锁,JDK5以后提供了一个新的锁对象Lock Lock是接口不能直接实例化,这里采用它的实现类ReentrantLock来实例化
ReentrantLock构造方法
方法名 说明 ReentrantLock() 创建一个ReentrantLock的实例static Lock lock = new ReentrantLock();
加锁解锁方法
方法名 说明 void lock() 获得锁 void unlock() 释放锁
实例:
public class Ticket implements Runnable {
private int ticket = 100 ;
private Object obj = new Object ( ) ;
private ReentrantLock lock = new ReentrantLock ( ) ;
@Override
public void run ( ) {
while ( true ) {
try {
lock. lock ( ) ;
if ( ticket <= 0 ) {
break ;
} else {
Thread . sleep ( 100 ) ;
ticket-- ;
System . out. println ( Thread . currentThread ( ) . getName ( ) + "在卖票,还剩下" + ticket + "张票" ) ;
}
} catch ( InterruptedException e) {
e. printStackTrace ( ) ;
} finally {
lock. unlock ( ) ;
}
}
}
}
public class Demo {
public static void main ( String [ ] args) {
Ticket ticket = new Ticket ( ) ;
Thread t1 = new Thread ( ticket) ;
Thread t2 = new Thread ( ticket) ;
Thread t3 = new Thread ( ticket) ;
t1. setName ( "窗口一" ) ;
t2. setName ( "窗口二" ) ;
t3. setName ( "窗口三" ) ;
t1. start ( ) ;
t2. start ( ) ;
t3. start ( ) ;
}
}
生产者消费者
方法名 说明 void wait() 导致当前线程等待,直到另一个线程调用该对象的 notify()方法或 notifyAll()方法 void notify() 唤醒正在等待对象监视器的单个线程 void notifyAll() 唤醒正在等待对象监视器的所有线程
桌子类(Desk): 定义表示包子数量的变量,定义锁对象变量,定义标记桌子上有无包子的变量 生产者类(Cooker): 实现Runnable接口,重写run()方法,设置线程任务 消费者类(Foodie): 实现Runnable接口,重写run()方法,设置线程任务 测试类(Demo): 里面有main方法,main方法中的代码步骤如下:1创建生产者线程和消费者线程对象2.分别开启两个线程
public class Desk {
public static boolean flag = false ;
public static int count = 10 ;
public static final Object lock = new Object ( ) ;
}
public class Cooker extends Thread {
@Override
public void run ( ) {
while ( true ) {
synchronized ( Desk . lock) {
if ( Desk . count == 0 ) {
break ;
} else {
if ( ! Desk . flag) {
System . out. println ( "厨师正在生产汉堡包" ) ;
Desk . flag = true ;
Desk . lock. notifyAll ( ) ;
} else {
try {
Desk . lock. wait ( ) ;
} catch ( InterruptedException e) {
e. printStackTrace ( ) ;
}
}
}
}
}
}
}
public class Foodie extends Thread {
@Override
public void run ( ) {
while ( true ) {
synchronized ( Desk . lock) {
if ( Desk . count == 0 ) {
break ;
} else {
if ( Desk . flag) {
System . out. println ( "吃货在吃汉堡包" ) ;
Desk . flag = false ;
Desk . lock. notifyAll ( ) ;
Desk . count-- ;
} else {
try {
Desk . lock. wait ( ) ;
} catch ( InterruptedException e) {
e. printStackTrace ( ) ;
}
}
}
}
}
}
}
public class Demo {
public static void main ( String [ ] args) {
Foodie f = new Foodie ( ) ;
Cooker c = new Cooker ( ) ;
f. start ( ) ;
c. start ( ) ;
}
}
进阶版:
将Desk类中的变量,采用面向对象的方式封装起来 生产者和消费者类中构造方法接收Desk类对象,之后在run方法中进行使用 创建生产者和消费者线程对象,构造方法中传入Desk类对象 开启两个线程
public class Desk {
private boolean flag;
private int count;
private final Object lock = new Object ( ) ;
public Desk ( ) {
this ( false , 10 ) ;
}
public Desk ( boolean flag, int count) {
this . flag = flag;
this . count = count;
}
public boolean isFlag ( ) {
return flag;
}
public void setFlag ( boolean flag) {
this . flag = flag;
}
public int getCount ( ) {
return count;
}
public void setCount ( int count) {
this . count = count;
}
public Object getLock ( ) {
return lock;
}
@Override
public String toString ( ) {
return "Desk{" +
"flag=" + flag +
", count=" + count +
", lock=" + lock +
'}' ;
}
}
public class Cooker extends Thread {
private Desk desk;
public Cooker ( Desk desk) {
this . desk = desk;
}
@Override
public void run ( ) {
while ( true ) {
synchronized ( desk. getLock ( ) ) {
if ( desk. getCount ( ) == 0 ) {
break ;
} else {
if ( ! desk. isFlag ( ) ) {
System . out. println ( "厨师正在生产汉堡包" ) ;
desk. setFlag ( true ) ;
desk. getLock ( ) . notifyAll ( ) ;
} else {
try {
desk. getLock ( ) . wait ( ) ;
} catch ( InterruptedException e) {
e. printStackTrace ( ) ;
}
}
}
}
}
}
}
public class Foodie extends Thread {
private Desk desk;
public Foodie ( Desk desk) {
this . desk = desk;
}
@Override
public void run ( ) {
while ( true ) {
synchronized ( desk. getLock ( ) ) {
if ( desk. getCount ( ) == 0 ) {
break ;
} else {
if ( desk. isFlag ( ) ) {
System . out. println ( "吃货在吃汉堡包" ) ;
desk. setFlag ( false ) ;
desk. getLock ( ) . notifyAll ( ) ;
desk. setCount ( desk. getCount ( ) - 1 ) ;
} else {
try {
desk. getLock ( ) . wait ( ) ;
} catch ( InterruptedException e) {
e. printStackTrace ( ) ;
}
}
}
}
}
}
}
public class Demo {
public static void main ( String [ ] args) {
Desk desk = new Desk ( ) ;
Foodie f = new Foodie ( desk) ;
Cooker c = new Cooker ( desk) ;
f. start ( ) ;
c. start ( ) ;
}
}
阻塞队列-连接生产者和消费者的管道
单列集合
ArrayBlockingQueue 底层是数组,有界ArrayBlockingQueue<String> arrayBlockingQueue = new ArrayBlockingQueue<>(1);
LinkedBlockingQueue: 底层是链表,无界.但不是真正的无界,最大为int的最大值
put(anObject): 将参数放入队列,如果放不进去会阻塞arrayBlockingQueue.put("汉堡包");
take(): 取出第一个数据,取不到会阻塞arrayBlockingQueue.take();
public class Demo02 {
public static void main ( String [ ] args) throws Exception {
ArrayBlockingQueue < String > arrayBlockingQueue = new ArrayBlockingQueue < > ( 1 ) ;
arrayBlockingQueue. put ( "汉堡包" ) ;
System . out. println ( arrayBlockingQueue. take ( ) ) ;
System . out. println ( arrayBlockingQueue. take ( ) ) ;
System . out. println ( "程序结束了" ) ;
}
}
生产者消费者用阻塞队列实现
public class Cooker extends Thread {
private ArrayBlockingQueue < String > bd;
public Cooker ( ArrayBlockingQueue < String > bd) {
this . bd = bd;
}
@Override
public void run ( ) {
while ( true ) {
try {
bd. put ( "汉堡包" ) ;
System . out. println ( "厨师放入一个汉堡包" ) ;
} catch ( InterruptedException e) {
e. printStackTrace ( ) ;
}
}
}
}
public class Foodie extends Thread {
private ArrayBlockingQueue < String > bd;
public Foodie ( ArrayBlockingQueue < String > bd) {
this . bd = bd;
}
@Override
public void run ( ) {
while ( true ) {
try {
String take = bd. take ( ) ;
System . out. println ( "吃货将" + take + "拿出来吃了" ) ;
} catch ( InterruptedException e) {
e. printStackTrace ( ) ;
}
}
}
}
public class Demo {
public static void main ( String [ ] args) {
ArrayBlockingQueue < String > bd = new ArrayBlockingQueue < > ( 1 ) ;
Foodie f = new Foodie ( bd) ;
Cooker c = new Cooker ( bd) ;
f. start ( ) ;
c. start ( ) ;
}
}
线程池-Executors默认线程池
线程池也是可以看做成一个池子,在该池子中存储很多个线程。 系统创建一个线程的成本是比较高的,因为它涉及到与操作系统交互,当程序中需要创建大量生存期很短暂的线程时,频繁的创建和销毁线程对系统的资源消耗有可能大于业务处理是对系统资源的消耗,这样就有点"舍本逐末"了。针对这一种情况,为了提高性能,我们就可以采用线程池。线程池在启动的时,会创建大量空闲线程,当我们向线程池提交任务的时,线程池就会启动一个线程来执行该任务。等待任务执行完毕以后,线程并不会死亡,而是再次返回到线程池中称为空闲状态。等待下一次任务的执行
static ExecutorService newCachedThreadPool() 创建一个默认的线程池ExecutorService executorService = Executors.newCachedThreadPool();
static newFixedThreadPool(int nThreads) 创建一个指定最多线程数量的线程池ExecutorService executorService = Executors.newFixedThreadPool(10);
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(核心线程数量,最大线程数量,空闲线程最大存活时间,时间单位,任务队列,创建线程工厂,任务的拒绝策略); 创建线程池对象 ThreadPoolExecutor pool = new ThreadPoolExecutor(2,5,2,TimeUnit.SECONDS,new ArrayBlockingQueue<>(10), Executors.defaultThreadFactory(),new ThreadPoolExecutor.AbortPolicy());
线程池参数
线程池参数 参数说明 corePoolSize: 核心线程的最大值,不能小于0 maximumPoolSize: 最大线程数,不能小于等于0,maximumPoolSize >= corePoolSize keepAliveTime: 空闲线程最大存活时间,不能小于0 unit: 时间单位 workQueue: 任务队列,不能为null threadFactory: 创建线程工厂,不能为null handler: 任务的拒绝策略,不能为null
任务的拒绝策略
ThreadPoolExecutor.AbortPolicy: 丢弃任务并抛出RejectedExecutionException异常。是默认的策略。 ThreadPoolExecutor.DiscardPolicy: 丢弃任务,但是不抛出异常 这是不推荐的做法。 ThreadPoolExecutor.DiscardOldestPolicy: 抛弃队列中等待最久的任务 然后把当前任务加入队列中。 ThreadPoolExecutor.CallerRunsPolicy: 调用任务的run()方法绕过线程池直接执行。(pool-1-thread-1---->> 执行了任务;pool-1-thread-3---->> 执行了任务;pool-1-thread-2---->> 执行了任务;pool-1-thread-1---->> 执行了任务;main---->> 执行了任务)
package com. itheima. mythreadpool ;
import java. util. concurrent. ExecutorService ;
import java. util. concurrent. Executors ;
public class MyThreadPoolDemo {
public static void main ( String [ ] args) throws InterruptedException {
ExecutorService executorService = Executors . newCachedThreadPool ( ) ;
executorService. submit ( ( ) -> {
System . out. println ( Thread . currentThread ( ) . getName ( ) + "在执行了" ) ;
} ) ;
executorService. submit ( ( ) -> {
System . out. println ( Thread . currentThread ( ) . getName ( ) + "在执行了" ) ;
} ) ;
executorService. shutdown ( ) ;
}
}
volatile
当A线程修改了共享数据时,B线程没有及时获取到最新的值,如果还在使用原先的值,就会出现问题 Volatile关键字 : 强制线程每次在使用的时候,都会看一下共享区域最新的值
package com. itheima. myvolatile ;
public class Demo {
public static void main ( String [ ] args) {
MyThread1 t1 = new MyThread1 ( ) ;
t1. setName ( "小路同学" ) ;
t1. start ( ) ;
MyThread2 t2 = new MyThread2 ( ) ;
t2. setName ( "小皮同学" ) ;
t2. start ( ) ;
}
}
package com. itheima. myvolatile ;
public class Money {
public static volatile int money = 100000 ;
}
package com. itheima. myvolatile ;
public class MyThread1 extends Thread {
@Override
public void run ( ) {
while ( Money . money == 100000 ) {
}
System . out. println ( "结婚基金已经不是十万了" ) ;
}
}
package com. itheima. myvolatile ;
public class MyThread2 extends Thread {
@Override
public void run ( ) {
try {
Thread . sleep ( 10 ) ;
} catch ( InterruptedException e) {
e. printStackTrace ( ) ;
}
Money . money = 90000 ;
}
}
线程状态
线程的状态被存在java.lang.Thread.State枚举类中
public class Thread {
public enum State {
NEW ,
RUNNABLE ,
BLOCKED ,
WAITING ,
TIMED_WAITING ,
TERMINATED;
}
public State getState ( ) {
return jdk. internal. misc. VM. toThreadState ( threadStatus) ;
}
}
线程存在6种状态:
线程状态 具体含义 NEW 初始状态 .一个尚未启动的线程的状态。也称之为初始状态、开始状态。线程刚被创建,但是并未启动。还没调用start方法。MyThread t = new MyThread()只有线程象,没有线程特征。RUNNABLE 可执行状态 .当我们调用线程对象的start方法,那么此时线程对象进入了RUNNABLE状态。那么此时才是真正的在JVM进程中创建了一个线程,线程一经启动并不是立即得到执行,线程的运行与否要听令与CPU的调度,那么我们把这个中间状态称之为可执行状态(RUNNABLE)也就是说它具备执行的资格,但是并没有真正的执行起来而是在等待CPU的度。BLOCKED 上锁状态 当一个线程试图获取一个对象锁,而该对象锁被其他的线程持有,则该线程进入Blocked状态;当该线程持有锁时,该线程将变成Runnable状态。WAITING 等待状态 一个正在等待的线程的状态。也称之为等待状态。造成线程等待的原因有两种,分别是调用Object.wait()、join()方法。处于等待状态的线程,正在等待其他线程去执行一个特定的操作。例如:因为wait()而等待的线程正在等待另一个线程去调用notify()或notifyAll();一个因为join()而等待的线程正在等待另一个线程结束。TIMED_WAITING 限时等待状态 一个在限定时间内等待的线程的状态。造成线程限时等待状态的原因有三种,分别是:Thread.sleep(long),Object.wait(long)、join(long)。TERMINATED 一个完全运行完成的线程的状态。也称之为终止状态、结束状态
原子性
原子性是指在一次操作或者多次操作中,要么所有的操作全部都得到了执行并且不会受到任何因素的干扰而中断,要么所有的操作都不执行,多个操作是一个不可以分割的整体。 java从JDK1.5开始提供了java.util.concurrent.atomic包(简称Atomic包),这个包中的原子操作类提供了一种用法简单,性能高效,线程安全地更新一个变量的方式。
AtomicBoolean: 原子更新布尔类型 AtomicInteger: 原子更新整型 AtomicLong: 原子更新长整型
以上3个类提供的方法几乎一模一样,所以本节仅以AtomicInteger为例进行讲解
AtomicInteger的常用方法如下:
public AtomicInteger(): 初始化一个默认值为0的原子型IntegerAtomicInteger ac = new AtomicInteger();
public AtomicInteger(int initialValue): 初始化一个指定值的原子型IntegerAtomicInteger ac2 = new AtomicInteger(10);
int get(): 获取值ac1.get()
int getAndIncrement(): 以原子方式将当前值加1,注意,这里返回的是自增前的值。int andIncrement = ac2.getAndIncrement();
int incrementAndGet(): 以原子方式将当前值加1,注意,这里返回的是自增后的值。int i = ac3.incrementAndGet();
int addAndGet(int data): 以原子方式将输入的数值与实例中的值(AtomicInteger里的value)相加,并返回结果。int i = ac4.addAndGet(20);
int getAndSet(int value): 以原子方式设置为newValue的值,并返回旧值。int andSet = ac5.getAndSet(20);
AtomicInteger