juc//java工具类
小结:
java工具类,lock和synchronize的使用 Lock lock=new ReentrantLock();
private Condition condition1=lock.newCondition();可以精准控制线程
8锁现象等
这个是看b站狂神视频总结的一些笔记,用于日后复习。
java查看线程的几个状态的类
//java查看线程转态
//Thread.State.
public enum State {
//新建
NEW,
RUNNABLE,
BLOCKED,
WAITING,
//超时等待
TIMED_WAITING,
TERMINATED;
}
synchronized
//实现订单实例
import java.util.Scanner;
public class test {
public static void main(String[] args) {
miapiao m=new miapiao();
Thread t=new Thread(()->{
for (int i=0;i<40;i++){
m.mai();
}
//java查看线程转态
//Thread.State.
},"a");
new Thread(()->{
for (int i=0;i<40;i++){
m.mai();
}
},"b").start();
new Thread(()->{
for (int i=0;i<40;i++){
m.mai();
}
},"c").start();
}
}
class miapiao{
private int num=20;
synchronized void mai(){
if(num>0){
System.out.println(Thread.currentThread().getName()+"票数"+num--+"剩余"+num);
}
}
}
lock锁
//创建锁对象
//锁住操作代码
//解锁
class miapiao2{
//创建锁对象
//锁住操作代码
//解锁
private int num=20;
Lock lock=new ReentrantLock();
public void mai(){
lock.lock();
try {
if(num>0){
System.out.println(Thread.currentThread().getName()+"票数"+num--+"剩余"+num);
}
}catch (Exception e){
e.printStackTrace();
}finally {
lock.unlock();
}
}
}
lock和synchronize的区别
synchronize 内置关键字 lock是一个java类
synchronize 无法判断获取锁的状态,lock可以判断是否获取了锁
synchronize会释放锁,lock需要手动释放,如果不释放就会死锁
synchronize线程1 获得锁,线程2就会等待,lock不一定会等待
synchronize可重入锁,不可以中断锁,非公平;lock可以判断锁
synchronize适合少量代码同步,;lock适合锁大量同步代码
锁是什么,如何判断锁的是谁
1.生产者消费者问题
package pc;
public class pc {
public static void main(String[] args) {
Data data=new Data();
new Thread(()->{
for (int i=0;i<10;i++){
try {
data.increment();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"a").start();
new Thread(()->{
for (int i=0;i<10;i++){
try {
data.decrement();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"b").start();
}
}
class Data{
private int number=0;
public synchronized void increment() throws InterruptedException {
if (number!=0){
this.wait();
}
number++;
System.out.println(Thread.currentThread().getName()+"=>"+number);
this.notifyAll();
}
public synchronized void decrement() throws InterruptedException {
if (number==0){
this.wait();
}
number--;
System.out.println(Thread.currentThread().getName()+"=>"+number);
this.notifyAll();
}
}
存在问题
虚假唤醒,等待应该穿在while中
要把if换成while
2.新版本pc问题使用lock解决
package pc;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class pc2 {
public static void main(String[] args) {
Data2 data2=new Data2();
new Thread(()->{
for (int i=0;i<10;i++){
try {
data2.increment();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"a").start();
new Thread(()->{
for (int i=0;i<10;i++){
try {
data2.decrement();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"b").start();
}
}
//ctrl+alt+t快捷键
class Data2{
private int number=0;
Lock lock=new ReentrantLock();
Condition condition=lock.newCondition();
// condition.await();等待
// condition.signalAll();唤醒
public void increment() throws InterruptedException {
lock.lock();
try {
if (number!=0){
condition.await();
}
number++;
System.out.println(Thread.currentThread().getName()+"=>"+number);
condition.signalAll();
}catch (Exception e){
e.printStackTrace();
}finally {
lock.unlock();
}
}
public void decrement() throws InterruptedException {
lock.lock();
try {
if (number==0){
condition.await();
}
number--;
System.out.println(Thread.currentThread().getName()+"=>"+number);
condition.signalAll();
}catch (Exception e ){
e.printStackTrace();
}finally {
lock.unlock();
}
}
}
3.condition精准唤醒线程
package pc;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class test3 {
public static void main(String[] args) {
Data3 data3=new Data3();
new Thread(()->{
for (int i=0;i<10;i++){
data3.printa();
}
},"a").start();
new Thread(()->{
for (int i=0;i<10;i++){
data3.printb();
}
},"b").start();
new Thread(()->{
for (int i=0;i<10;i++){
data3.printc();
}
},"c").start();
}
}
class Data3{
private Lock lock=new ReentrantLock();
private Condition condition1=lock.newCondition();
private Condition condition2=lock.newCondition();
private Condition condition3=lock.newCondition();
private int number=1;
public void printa(){
lock.lock();
try {
//业务,贩毒案,执行,通知
while (number!=1){
condition1.await();
}
System.out.println(Thread.currentThread().getName()+"===>>>aaa");
number=2;
condition2.signal();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public void printb(){
lock.lock();
try {
//业务,贩毒案,执行,通知
while (number!=2){
condition2.await();
}
System.out.println(Thread.currentThread().getName()+"===>>>aaa");
number=3;
condition3.signal();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public void printc(){
lock.lock();
try {
//业务,贩毒案,执行,通知
while (number!=3){
condition3.await();
}
System.out.println(Thread.currentThread().getName()+"===>>>cccc");
number=1;
condition1.signal();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
4.8锁现象
深刻理解锁
说到底,就是看锁的是不是同一个对象,如果不是同一个对象象就要不需要等待,如果是同一个对象就要等待。
new
static class
如果是同一个锁就看谁先获得,如果不是同一个锁,就看休眠时间。
5.集合类不安全
list不安全
package unsafelist;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.CopyOnWriteArrayList;
public class ListTest {
public static void main(String[] args) {
// List<String> list=new ArrayList<>();
//线程安全
// 1.List<String> list= Collections.synchronizedList(new ArrayList<>());
List<String> list= new CopyOnWriteArrayList<>();
for (int i=0;i<10;i++){
new Thread(()->{
list.add(UUID.randomUUID().toString().substring(0,5));
System.out.println(list);
}).start();
}
}
}
set
package unsafelist;
import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CopyOnWriteArraySet;
public class SetTest {
public static void main(String[] args) {
// Set<String> set=new HashSet<>();
// Set<String> set= Collections.synchronizedSet(new HashSet<>());
// Set<String> set=new CopyOnWriteArraySet<>();
//hashset底层就是hashmap
// public boolean add(E e) {
// return map.put(e, PRESENT)==null;
// }
Set<String> set=new CopyOnWriteArraySet<>();
for (int i=0;i<10;i++){
new Thread(()->{
set.add(UUID.randomUUID().toString().substring(0,5));
System.out.println(set);
}).start();
}
}
}
map
map
默认等价? new hashmap(16,0.75);
6.callable
package callabletest;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
public class Test {
public static void main(String[] args) throws ExecutionException, InterruptedException {
Mythread mythread=new Mythread();
FutureTask futureTask=new FutureTask(mythread);
new Thread(futureTask,"a").start();
Integer a=(Integer)futureTask.get();
System.out.println(a);
}
}
class Mythread implements Callable<Integer>{
@Override
public Integer call() throws Exception {
System.out.println("call");
return 1024;
}
}
7.常用的辅助类
CountDownLatch减法计数器
package callabletest;
import java.util.concurrent.CountDownLatch;
//减法计数器
public class CountDownLatch2 {
public static void main(String[] args) throws InterruptedException {
CountDownLatch countDownLatch=new CountDownLatch(6);
for (int i=1;i<=6;i++){
new Thread(()->{
System.out.println(Thread.currentThread().getName()+"go out");
countDownLatch.countDown();
},String.valueOf(i)).start();
}
countDownLatch.wait();
System.out.println("结束");
//countDownLatch.countDown();数量-1
//当-到0就会countDownLatch.wait();唤醒
}
}
CyclicBarrier加法计数器
package callabletest;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
public class CyclicBarriertest {
//加法计数器
public static void main(String[] args) {
CyclicBarrier cyclicBarrier=new CyclicBarrier(7,()->{
System.out.println("数量到达");
});
for (int i=1;i<=7;i++){
final int tmp=i;
new Thread(()->{
//在lambda中拿到上面的i的变量通过中间变量final
System.out.println(tmp+Thread.currentThread().getName());
try {
cyclicBarrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}).start();
}
}
}
Semaphore信号量
package callabletest;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
public class Semaphoretest {
//信号量,限流
public static void main(String[] args) {
Semaphore semaphore=new Semaphore(3);
for (int i=1;i<=6;i++){
new Thread(()->{
try {
//获得
semaphore.acquire();
System.out.println(Thread.currentThread().getName()+"---get");
TimeUnit.SECONDS.sleep(2);
System.out.println(Thread.currentThread().getName()+"---leave");
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
//释放
semaphore.release();
}
},String.valueOf(i)).start();
}
}
}
8.读写锁ReadWriteLock
ReadWriteLock
写锁只能被一个线程占用
读锁可以被同时占用
package ReadWriteLocktest;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
public class ReadWriteLockDemo {
public static void main(String[] args) {
MyCachelock myCache=new MyCachelock();
for (int i=1;i<=6;i++){
final int tmp=i;
new Thread(()->{
myCache.put(tmp+"",tmp+"");
},String.valueOf(i)).start();
}
for (int i=1;i<=6;i++){
final int tmp=i;
new Thread(()->{
myCache.get(tmp+"");
},String.valueOf(i)).start();
}
}
}
class MyCache{
private volatile Map<String,Object> map=new HashMap<>();
public void put(String key,Object value){
System.out.println(Thread.currentThread().getName()+"写入"+key);
map.put(key,value);
System.out.println(Thread.currentThread().getName()+"写入ok" + "");
}
public void get(String key){
System.out.println(Thread.currentThread().getName()+"读取"+key);
map.get(key);
System.out.println(Thread.currentThread().getName()+"读取ok" + "");
}
}
class MyCachelock{
//读写锁
private ReadWriteLock readWriteLock=new ReentrantReadWriteLock();
private volatile Map<String,Object> map=new HashMap<>();
public void put(String key,Object value){
readWriteLock.writeLock().lock();
try {
System.out.println(Thread.currentThread().getName()+"写入"+key);
map.put(key,value);
System.out.println(Thread.currentThread().getName()+"写入ok" + "");
} catch (Exception e) {
e.printStackTrace();
} finally {
readWriteLock.writeLock().unlock();
}
}
public void get(String key){
readWriteLock.readLock().lock();
try {
System.out.println(Thread.currentThread().getName()+"读取"+key);
map.get(key);
System.out.println(Thread.currentThread().getName()+"读取ok" + "");
} catch (Exception e) {
e.printStackTrace();
} finally {
readWriteLock.readLock().unlock();
}
}
}
10阻塞队列
阻塞:如果队列阻塞,就必须等待
队列
什么情况下用阻塞队列
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AUtHHBfz-1638085874752)(C:\Users\gym\AppData\Roaming\Typora\typora-user-images\image-20211126144822704.png)]
四组api
抛出异常
不会抛出异常
阻塞
超时等待
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-G1aGDBwB-1638085874755)(C:\Users\gym\AppData\Roaming\Typora\typora-user-images\image-20211126150115867.png)]
package BlockingQueueTest;
import java.util.concurrent.ArrayBlockingQueue;
public class BlockingQueueDemo {
public static void main(String[] args) {
BlockingQueueDemo.test1();
}
public static void test1(){
ArrayBlockingQueue blockingQueue=new ArrayBlockingQueue<>(3);
System.out.println(blockingQueue.add("a"));
System.out.println(blockingQueue.add("b"));
System.out.println(blockingQueue.add("c"));
//再+就异常
System.out.println("----------------------");
System.out.println(blockingQueue.remove());
System.out.println(blockingQueue.remove());
System.out.println(blockingQueue.remove());
//再-就异常
//.poll()有返回值,不报错
}
}
同步队列SynchronousQueue
进一个必须取出一个
package BlockingQueueTest;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.SynchronousQueue;
public class SynchronousQueueTest {
public static void main(String[] args) {
BlockingQueue<String> synchronousQueue=new SynchronousQueue<>();
new Thread(()->{
try {
System.out.println(Thread.currentThread().getName()+"put 1");
synchronousQueue.put("1");
System.out.println(Thread.currentThread().getName()+"put 2");
synchronousQueue.put("2");
System.out.println(Thread.currentThread().getName()+"put 3");
synchronousQueue.put("3");
} catch (InterruptedException e) {
e.printStackTrace();
}
},"t1").start();
new Thread(()->{
try {
System.out.println(Thread.currentThread().getName()+"----"+synchronousQueue.take());
System.out.println(Thread.currentThread().getName()+"---"+synchronousQueue.take());
System.out.println(Thread.currentThread().getName()+"--"+synchronousQueue.take());
} catch (InterruptedException e) {
e.printStackTrace();
}
},"t2").start();
}
}
10线程池
池化技术
程序的运行,本质,占用痛资源!优化资源的使用,=》赤化技术
降低资源的消耗
提高响应速度
方便管理
线程复用,可以控制最大并发数,管理线程
3大方法7大参数4种策略
package pool;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
//Executors三大方法
public class TestPool {
public static void main(String[] args) {
// Executors.newSingleThreadExecutor();//单个线程
// Executors.newFixedThreadPool(5);
// Executors.newCachedThreadPool();//可伸缩线程池
// ExecutorService executorService=Executors.newSingleThreadExecutor();
ExecutorService executorService=Executors.newFixedThreadPool(5);
try {
for (int i=1;i<10;i++){
executorService.execute(()->{
System.out.println(Thread.currentThread().getName()+"ok");
});
}
} finally {
executorService.shutdown();
}
}
}
7大参数
public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>()));
}
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
Executors.defaultThreadFactory(), defaultHandler);
}
package pool;
import java.util.concurrent.*;
//Executors三大方法
public class TestPool {
public static void main(String[] args) {
Executors.newSingleThreadExecutor();//单个线程
// Executors.newFixedThreadPool(5);
// Executors.newCachedThreadPool();//可伸缩线程池
// ExecutorService executorService=Executors.newSingleThreadExecutor();
// ExecutorService executorService=Executors.newFixedThreadPool(5);
//自定义线程池
ExecutorService executorService=new ThreadPoolExecutor(
2,
5,
3,
TimeUnit.SECONDS,
new LinkedBlockingDeque<>(),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.AbortPolicy()//拒绝策略,满了就抛出异常,四种策略
);
try {
for (int i=1;i<10;i++){
executorService.execute(()->{
System.out.println(Thread.currentThread().getName()+"ok");
});
}
} finally {
executorService.shutdown();
}
}
}
CPU密集型:几核就是几,cpu效率最高
Runtime.getRuntime().availableProcessors();
io密集型:判断你的程序中io 的线程
11四大函数式接口
lambda表达式,链式编程,函数式接口,Stream流式计算
函数式接口:只有一个方法的接口
//Runable
public abstract void run();
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RHosgqkX-1638085874758)(C:\Users\gym\AppData\Roaming\Typora\typora-user-images\image-20211126181620267.png)]
四大原生函数式接口
package hanshu;
import java.util.function.Function;
public class FunctionTest {
public static void main(String[] args) {
//一个输入一个输出
//只要是函数式接口就诶lambda
// Function function=new Function<String,String>(){
// @Override
// public String apply(String o) {
// return o;
// }
// };
Function function=(str)->{ return str; };
System.out.println(function.apply("123"));
}
}
断定型接口
package hanshu;
import java.util.function.Predicate;
public class PredicateTest {
//断定型接口
public static void main(String[] args) {
// Predicate predicate=new Predicate<String>() {
// @Override
// public boolean test(String o) {
// return o.isEmpty();
// }
// };
Predicate<String> predicate=(str)->{return str.isEmpty();};
System.out.println(predicate.test("123"));
}
}
消费型接口,供给型接口
package hanshu;
import java.util.function.Consumer;
import java.util.function.Supplier;
public class ConsumerTest {
public static void main(String[] args) {
//消费型接口
Consumer consumer=new Consumer<String>() {
@Override
public void accept(String o) {
System.out.println(o);
}
};
Consumer<String> consumer1=(str)->{ System.out.println(str); };
consumer1.accept("123");
Supplier supplier=new Supplier<Integer>() {
@Override
public Integer get() {
return 1204;
}
};
Supplier<Integer> supplier1=()->{return 1024;};
System.out.println(supplier1.get());
}
}
12Stream流式计算
大数据=存储+计算
流式计算
package stream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class Util {
public static void main(String[] args) {
User u1=new User(1,"a",21);
User u2=new User(2,"b",22);
User u3=new User(3,"c",23);
User u4=new User(4,"d",24);
User u5=new User(6,"e",25);
//集合用于存储
List<User> list= Arrays.asList(u1,u2,u3,u4,u5);
//stream计算
//链式编程
list.stream().filter(u->{return u.getId()%2==0;})
.filter(u->{return u.getAge()>23;})
.map(u->{return u.getName().toUpperCase();})
.sorted((uu1,uu2)->{return uu2.compareTo(uu1);})
.limit(1)
.forEach(System.out::println);
}
}
13ForkJoin
什么是ForkJoin
1.7之后出来的,并发执行任务,提高效率,大数据量
特点:工作窃取
三种对大数据的处理方式
package forkjoin;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ForkJoinTask;
import java.util.stream.LongStream;
public class Test {
public static void main(String[] args) throws ExecutionException, InterruptedException {
// Test.test1();//3768
// Test.test2();//5231
Test.test3();//497
}
public static void test1(){
Long sum=0L;
long start=System.currentTimeMillis();
for (long i=1L;i<=10_0000_0000L;i++){
sum+=i;
}
long end=System.currentTimeMillis();
System.out.println("sum="+sum+"时间="+(end-start));
}
public static void test2() throws ExecutionException, InterruptedException {
long start=System.currentTimeMillis();
ForkJoinPool forkJoinPool=new ForkJoinPool();
ForkJoinTask<Long> tasl=new ForkjoinTest(0L,10_0000_0000L);
ForkJoinTask<Long> submit=forkJoinPool.submit(tasl);
Long sum=submit.get();
long end=System.currentTimeMillis();
System.out.println("sum="+sum+"时间="+(end-start));
}
public static void test3(){
long start=System.currentTimeMillis();
long sum=LongStream.rangeClosed(0L,10_0000_0000L).parallel().reduce(0,Long::sum);
long end=System.currentTimeMillis();
System.out.println("sum="+sum+"时间="+(end-start));
}
}
14异步回调
Future
package future;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
public class FutureTest {
public static void main(String[] args) throws ExecutionException, InterruptedException {
//发起一个请求
//没有返回值的异步回调
// CompletableFuture<Void> completableFuture=CompletableFuture.runAsync(()->{
// try {
// TimeUnit.SECONDS.sleep(2);
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
// System.out.println(Thread.currentThread().getName()+"runAsync+>voi");
// });
// System.out.println("1111");
// completableFuture.get();//获得执行结果
CompletableFuture<Integer> completableFuture=CompletableFuture.supplyAsync(()->{
System.out.println(Thread.currentThread().getName()+"runAsync+>integer");
return 1024;
});
System.out.println("123");
completableFuture.get();
}
}
15理解jmm
对volatile的理解
volatile是java轻量级的同步机制
1.可见性
2.不保证原子性
3.禁止指令重排
jmm:java内存模型
关于jmm的一些同步约定
1线程解锁前,必须把共享变量理立刻刷回主存
2线程加锁前,必须读取主存中最新的值
3.加锁和解锁是同一个锁
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aXxSP87E-1638085874762)(C:\Users\gym\AppData\Roaming\Typora\typora-user-images\image-20211127174640649.png)]
内存模型-同步八种操作
1:lock: 把主内存变量标识为一条线程独占,此时不允许其他线程对此变量进行读写。
2:unlock:解锁一个主内存变量。
3:read: 把一个主内存变量值读入到线程的工作内存,强调的是读入这个过程。
4:load: 把read到变量值保存到线程工作内存中作为变量副本,强调的是读入的值的保存过程。
5:use: 线程执行期间,把工作内存中的变量值传给字节码执行引擎。
6:assign(赋值):字节码执行引擎把运算结果传回工作内存,赋值给工作内存中的结果变量。
7:store: 把工作内存中的变量值传送到主内存,强调传送的过程。
8:write: 把store传送进来的变量值写入主内存的变量中,强调保存的过程。
16volatile
保证可见性
package jmm;
import java.util.concurrent.TimeUnit;
public class JmmTest {
//可见性
private volatile static int num=0;
public static void main(String[] args) {
//线程不知道主存的值已经改变了
new Thread(()->{
while (num==0){
}
}).start();
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
num=1;
System.out.println(num);
}
}
不保证原子性
线程a执行任务时不能被分割
package jmm;
public class Test2 {
private static volatile int num=0;
public static void add(){
num++;
}
public static void main(String[] args) {
for (int i=1;i<20;i++){
new Thread(()->{
for (int j=1;j<=1000;j++){
add();
}
}).start();
}
while (Thread.activeCount()>2){
Thread.yield();
}
System.out.println(Thread.currentThread().getName()+"---"+num);
}
}
不加lock和synchronize保证原子性
package jmm;
import java.util.concurrent.atomic.AtomicInteger;
public class Test2 {
private static volatile AtomicInteger num=new AtomicInteger();
public static void add(){
num.getAndIncrement();//AtomicInteger+1
}
public static void main(String[] args) {
for (int i=1;i<=20;i++){
new Thread(()->{
for (int j=1;j<=1000;j++){
add();
}
}).start();
}
while (Thread.activeCount()>2){
Thread.yield();
}
System.out.println(Thread.currentThread().getName()+"---"+num);
}
}
17指令重排
源代码》编译器优化的重排》指令并行也可能会重排》内存系统会重排》执行
写的程序不一定按照顺序执行,系统会判断关联性再执行
volatile可以防止指令重排
18单例模式
19CAS 比较并交换
通过unsafe类操作内存,效率更快比较工作内存中的值和主内存中的值,这个值是期望的,那么就执行操作
缺:
自旋的
循环耗时
一次性只能保证一个共享变量的值
aba问题
package cas;
import java.util.concurrent.atomic.AtomicInteger;
public class Test {
public static void main(String[] args) {
//cas:比较和交换
AtomicInteger atomicInteger=new AtomicInteger(2020);
atomicInteger.compareAndSet(2020,2021);
System.out.println(atomicInteger.get());
atomicInteger.compareAndSet(2020,2021);
System.out.println(atomicInteger.get());
}
}
ABA
已经动过手脚的数据
package cas;
import java.util.concurrent.atomic.AtomicInteger;
public class Test {
public static void main(String[] args) {
//cas:比较和交换
AtomicInteger atomicInteger=new AtomicInteger(2020);
//捣乱
atomicInteger.compareAndSet(2020,2021);
System.out.println(atomicInteger.get());
atomicInteger.compareAndSet(2021,2020);
System.out.println(atomicInteger.get());
atomicInteger.compareAndSet(2020,6666);
System.out.println(atomicInteger.get());
}
}
原子引用
AtomicStampedReference<Integer> atomicStampedReference=new AtomicStampedReference<>(2020,1);
通过版本号控制
公平锁:不能插队
非公平锁:能插队
可重入锁
递归锁
拿到了外面的锁,就拿到了里面的锁
锁必须配对
//synchronized
package lock8;
public class Test3 {
public static void main(String[] args) {
PhoneTest phone=new PhoneTest();
new Thread(()->{
phone.sms();
},"A").start();
new Thread(()->{
phone.sms();
},"B").start();
}
}
class PhoneTest{
public synchronized void sms(){
System.out.println("smm-----------");
call();
}
public synchronized void call(){
System.out.println("call-----------");
}
}
//lock
package lock8;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class Test4 {
public static void main(String[] args) {
PhoneTest2 phone=new PhoneTest2();
new Thread(()->{
phone.sms();
},"A").start();
new Thread(()->{
phone.sms();
},"B").start();
}
}
class PhoneTest2{
Lock lock=new ReentrantLock();
public void sms(){
lock.lock();
try {
System.out.println("smm-----------");
call();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public void call(){
lock.lock();
try {
System.out.println("call-----------");
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
自旋锁
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1tjpL4mJ-1638085874764)(C:\Users\gym\AppData\Roaming\Typora\typora-user-images\image-20211127191606503.png)]
package lock8;
import java.util.concurrent.atomic.AtomicReference;
public class Test5 {
AtomicReference<Thread> atomicReference=new AtomicReference<>();
public void myLock(){
Thread thread= Thread.currentThread();
System.out.println(Thread.currentThread().getName()+"====>mylock");
//自旋锁
while (!atomicReference.compareAndSet(null,thread)){}
}
public void unmyLock(){
Thread thread= Thread.currentThread();
System.out.println(Thread.currentThread().getName()+"====>unmylock");
//
atomicReference.compareAndSet(thread,null);
}
}
死锁排查
试图获得对象的锁
日志
jps
jstack+进程号
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7WowZwIg-1638085874766)(C:\Users\gym\AppData\Roaming\Typora\typora-user-images\image-20211127195541981.png)]
s(){
lock.lock();
try {
System.out.println(“smm-----------”);
call();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public void call(){
lock.lock();
try {
System.out.println("call-----------");
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
##### **自旋锁**
[外链图片转存中...(img-1tjpL4mJ-1638085874764)]
```java
package lock8;
import java.util.concurrent.atomic.AtomicReference;
public class Test5 {
AtomicReference<Thread> atomicReference=new AtomicReference<>();
public void myLock(){
Thread thread= Thread.currentThread();
System.out.println(Thread.currentThread().getName()+"====>mylock");
//自旋锁
while (!atomicReference.compareAndSet(null,thread)){}
}
public void unmyLock(){
Thread thread= Thread.currentThread();
System.out.println(Thread.currentThread().getName()+"====>unmylock");
//
atomicReference.compareAndSet(thread,null);
}
}
死锁排查
试图获得对象的锁
日志
jps
jstack+进程号
[外链图片转存中…(img-7WowZwIg-1638085874766)]