实战JUC
1.JUC_volatile 关键字与内存可见性
/**
* Volatile 关键字:当多个线程进行操作共享数据时,可以保证内存中的数据可见。
* 相较于 synchroniced 是一种较为轻量的同步策略。
*
* 注意:
* 1、Volatile 不具备互斥性
* 2、Volatile不能保证变量的原子性
**/
先理解一下我画的图
这个图是没使用 Volatile 关键字的原理解析
这个是我使用了 Volatile 关键字操作共享变量的原理图
package com.hxx;
/**
* @ClassName HuangXiangXiang
* @Date 2020/8/4 0:04
* @Version V1.0
*
*
* Volatile 关键字:当多个线程进行操作共享数据时,可以保证内存中的数据可见。
* 相较于 synchroniced 是一种较为轻量的同步策略。
*
* 注意:
* 1、Volatile 不具备互斥性
* 2、Volatile不能保证变量的原子性
**/
public class TestVolatile {
public static void main(String[] args) {
ThreadDemo threadDemo = new ThreadDemo();
new Thread(threadDemo).start();
while (true) {
if (threadDemo.isFlag()) {
System.out.println("....................");
break;
}
}
}
}
class ThreadDemo implements Runnable {
//可根据这两个查看效果
private volatile boolean flag = false; //使用了volatile
// private volatile boolean flag = false; //不使用volatile
@Override
public void run() {
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
flag = true;
System.out.println("flag = " + isFlag());
}
public boolean isFlag() {
return flag;
}
public void setFlag(boolean flag) {
this.flag = flag;
}
}
2. JUC_原子变量与 CAS 算法
原子变量:jdk1.5后、java.util.concurrent.atomic 包下提供的原子变量
1、volatile 保证内存可见性
2、CAS (Compare-And-Swap) 算法保证数据原子性
CAS包含三个操作
内存值 V
预估值 A
更新值 B
当且仅当 V==A 时,V=B, 否则不做任何操作
原理图
package com.hxx;
import java.util.concurrent.atomic.AtomicInteger;
/**
* @ClassName HuangXiangXiang
* @Date 2020/8/4 23:02
* @Version V1.0
* <p>
* 读改写三个步骤
* 原子变量:jdk1.5后、java.util.concurrent.atomic 包下提供的原子变量
* * 1、volatile 保证内存可见性
* * 2、CAS (Compare-And-Swap) 算法保证数据原子性
* * CAS包含三个操作
* * 内存值 V
* * 预估值 A
* * 更新值 B
* * 当且仅当 V == A 时,V=B(才让B的值赋给V) , 否则不做任何操作
**/
public class TestAtomicDemo {
public static void main(String[] args) {
AtomicDemo ad = new AtomicDemo();
for (int i = 0; i < 10; i++) {
new Thread(ad).start();
}
}
}
class AtomicDemo implements Runnable {
// private int serialNumber = 0;
private AtomicInteger serialNumber = new AtomicInteger();
@Override
public void run() {
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(getSerialNumber());
}
public int getSerialNumber() {
return serialNumber.getAndIncrement(); //获取变量在++
}
}
3. JUC_模拟 CAS 算法
4. JUC_同步容器类 ConcurrentHashMap
画的原理图、很清晰
5. JUC_CountDownLatch 闭锁
package com.hxx;
import java.util.concurrent.CountDownLatch;
/**
* CountDownLatch 闭锁,在完成某些运算时、只有其他所有线程的运算全部完成,当前运算才能继续完成
*
* @ClassName HuangXiangXiang
* @Date 2020/8/17 21:48
* @Version V1.0
**/
public class TestCountDownLatch {
public static void main(String[] args) {
final CountDownLatch latch = new CountDownLatch(5);
LatchDemo ld = new LatchDemo(latch);
long start = System.currentTimeMillis();
for (int i = 0; i < 5; i++) {
new Thread(ld).start();
}
try {
//等待
latch.await();
} catch (InterruptedException e) {
}
long end = System.currentTimeMillis();
System.out.println("耗费时间为:" + (end - start));
}
}
class LatchDemo implements Runnable {
private CountDownLatch latch;
public LatchDemo(CountDownLatch latch) {
this.latch = latch;
}
@Override
public void run() {
//多个线程进来加了个锁、可能会线程安全
synchronized (this) {
try {
for (int i = 0; i < 50000; i++) {
if (i % 2 == 0) {
System.out.println(i);
}
}
} finally {
// 每次调用减一---不减成0 主线程就得等这
latch.countDown();
}
}
}
}
6. JUC_创建执行线程的方式三:实现 Callable
原理图带上
package com.apk;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
/**
* 创建执行线程方式三
* 实现Callable接口
* 相较于实现Runable 接口的方式,方法可以有返回值,并且可以抛出异常
*
* @Author 小坏
* @Date 2020/8/20 16:24
* @Version 1.0
* @program: 父工程 JUC 万物起源之地
*/
public class TestCallable {
public static void main(String[] args) throws ExecutionException {
ThreadDemo1 demo1 = new ThreadDemo1();
/**
* 这个方式他有返回值、所以要加一步--
* Callable 需要FutureTask 实现类的支持、用来接收运算结果的操作
* FutureTask 是 Future 接口的实现类
*/
FutureTask<Integer> result = new FutureTask<>(demo1);
new Thread(result).start(); //线程不执行完毕他就不会走下面的获取结果、跟闭锁类似
try {
Integer sum = result.get();
System.out.println(sum);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
class ThreadDemo1 implements Callable<Integer> {
@Override
public Integer call() throws Exception {
int sum = 0;
for (int i = 0; i < 100000000; i++) {
System.out.println(i);
sum += i;
}
return sum;
}
}
7. JUC_同步锁 Lock
package com.apk;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* 一、用多线程安全问题的方式
* synchronized:隐士锁
* 1、同步代码块
* 2、同步方法
* <p>
* jdk 1.5 后
* 3、同步锁 lock
* 注意:是一个显示锁,需要通过lock() 方法上锁,必须通过unlock() 方法进行释放锁
*
* @Author 小坏
* @Date 2020/8/20 17:12
* @Version 1.0
* @program: 父工程 JUC 万物起源之地
*/
public class TestLock {
public static void main(String[] args) {
Ticket ticket = new Ticket();
new Thread(ticket, "1号窗口").start();
new Thread(ticket, "2号窗口").start();
new Thread(ticket, "3号窗口").start();
}
}
class Ticket implements Runnable {
private int tick = 100;
private Lock lock = new ReentrantLock();
@Override
public void run() {
while (true) {
lock.lock(); //上锁
try {
if (tick > 0) {
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "完成售票,余票为:" + --tick);
}
} finally {
lock.unlock(); //手动释放锁
}
}
}
}
8. JUC_生产者消费者案例-虚假唤醒
9. JUC_Condition 线程通信
10. JUC_线程按序交替
11. JUC_ReadWriteLock 读写锁
12. JUC_线程八锁
13. JUC_线程池
14. JUC_线程调度
15. JUC_ForkJoinPool 分支合并框架-工
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/15543.html