1.什么是JUC
2.线程和进程
3.Lock锁(重点)
传统的synchronized锁
public class SaleTicketDemo01 {
public static void main(String[] args) {
//并发:多线程操作同一个资源,把资源类丢入线程
Ticket ticket = new Ticket();
//多线程操作
new Thread(()->{
for (int i = 0; i < 40; i++) {
ticket.sale();
}
},"A").start();
new Thread(()->{
for (int i = 0; i < 40; i++) {
ticket.sale();
}
},"B").start();
new Thread(()->{
for (int i = 0; i < 40; i++) {
ticket.sale();
}
},"C").start();
}
}
//资源类 OOP
class Ticket{
//属性、方法
private int number=30;
//卖票的方法
//synchronized 本质:队列,锁
public synchronized void sale(){
if(number>0){
System.out.println(Thread.currentThread().getName()+"卖出了"+(number--)+"票,剩余:"+number);
}
}
}
public class SaleTicketDemo02 {
public static void main(String[] args) {
//并发:多线程操作同一个资源,把资源类丢入线程
Ticket2 ticket = new Ticket2();
//多线程操作
new Thread(()->{for (int i = 0; i < 40; i++)ticket.sale();},"A").start();
new Thread(()->{for (int i = 0; i < 40; i++)ticket.sale();},"B").start();
new Thread(()->{for (int i = 0; i < 40; i++)ticket.sale();},"C").start();
}
}
//资源类 OOP
class Ticket2{
//属性、方法
private int number=30;
Lock lock=new ReentrantLock();
//卖票的方法
//synchronized 本质:队列,锁
public void sale(){
lock.lock();//加锁
try{
//业务代码
if(number>0){
System.out.println(Thread.currentThread().getName()+"卖出了"+(number--)+"票,剩余:"+number);
}
}catch (Exception e){
e.printStackTrace();
}finally {
lock.unlock(); //解锁
}
}
}
4.生产者和消费者问题
public class A {
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;
//+1
public synchronized void increment() throws InterruptedException {
if(number!=0){
//等待
this.wait();
}
number++;
System.out.println(Thread.currentThread().getName()+"==>"+number);
//通知其他线程,我+1完毕了
this.notifyAll();
}
//-1
public synchronized void decrement() throws InterruptedException {
if(number==0){
//等待
this.wait();
}
number--;
System.out.println(Thread.currentThread().getName()+"==>"+number);
//通知其他线程,我-1完毕了
this.notifyAll();
}
}
public class A {
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();
new Thread(()->{
for (int i = 0; i < 10; i++) {
try {
data.decrement();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"C").start();
new Thread(()->{
for (int i = 0; i < 10; i++) {
try {
data.decrement();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"D").start();
}
}
//判断等待,业务,通知
class Data{
private int number=0;
//+1
public synchronized void increment() throws InterruptedException {
while(number!=0){
//等待
this.wait();
}
number++;
System.out.println(Thread.currentThread().getName()+"==>"+number);
//通知其他线程,我+1完毕了
this.notifyAll();
}
//-1
public synchronized void decrement() throws InterruptedException {
while (number==0){
//等待
this.wait();
}
number--;
System.out.println(Thread.currentThread().getName()+"==>"+number);
//通知其他线程,我-1完毕了
this.notifyAll();
}
}
5.JUC版的生产者和消费者问题
代码实现
public class B {
public static void main(String[] args) {
Data2 data = new Data2();
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();
new Thread(()->{
for (int i = 0; i < 10; i++) {
try {
data.decrement();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"C").start();
new Thread(()->{
for (int i = 0; i < 10; i++) {
try {
data.decrement();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"D").start();
}
}
//判断等待,业务,通知
class Data2{
private int number=0;
Lock lock=new ReentrantLock();
Condition condition = lock.newCondition();
//condition.await();
//condition.signalAll();
//
//+1
public void increment() throws InterruptedException {
lock.lock();
try{
while(number!=0){
//等待
condition.await();
}
number++;
System.out.println(Thread.currentThread().getName()+"==>"+number);
//通知其他线程,我+1完毕了
condition.signalAll();
}catch (Exception e){
e.printStackTrace();
}finally {
lock.unlock();
}
}
//-1
public void decrement() throws InterruptedException {
lock.lock();
try{
while (number==0){
//等待
condition.await();
}
number--;
System.out.println(Thread.currentThread().getName()+"==>"+number);
//通知其他线程,我-1完毕了
condition.signalAll();
}catch (Exception e){
e.printStackTrace();
}finally {
lock.unlock();
}
}
}
A、B、C三个线程顺序执行
public class C {
public static void main(String[] args) {
Data3 data = new Data3();
new Thread(()->{
for (int i = 0; i < 10; i++) {
data.printA();
}
},"A").start();
new Thread(()->{
for (int i = 0; i < 10; i++) {
data.printB();
}
},"B").start();
new Thread(()->{
for (int i = 0; i < 10; i++) {
data.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;//1A 2B 3C
public void printA(){
lock.lock();
try {
//业务,判断—>执行->通知
while(number!=1){
//等待
condition1.await();
}
System.out.println(Thread.currentThread().getName()+"=>AAAAAA");
//唤醒,唤醒指定的人,B
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()+"=>BBBBBB");
//唤醒,唤醒指定的人,B
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()+"=>CCCCC");
//唤醒,唤醒指定的人,C
number=1;
condition1.signal();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
6.8锁问题
1.标准情况下,两个线程先打印发短信 还是打电话 1.发短信 2.打电话
/**
* 8锁,就是关于锁的8个问题
* 1.标准情况下,两个线程先打印发短信 还是打电话 1.发短信 2.打电话
*/
public class Test1 {
public static void main(String[] args) {
Phone phone = new Phone();
new Thread(()->{
phone.sendSms();
},"A").start();
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(()->{
phone.call();
},"B").start();
}
}
class Phone{
//synchronized 锁的对象是方法的调用者
//两个方法用的是同一个锁,谁先拿到谁先执行
public synchronized void sendSms(){
try {
TimeUnit.SECONDS.sleep(4);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("发短信");
}
public synchronized void call(){
System.out.println("打电话");
}
}
2.1标准情况下,两个线程先打印hello 还是打电话 1.hello 2.发短信
public class Test2 {
public static void main(String[] args) {
Phone2 phone = new Phone2();
new Thread(()->{
phone.sendSms();
},"A").start();
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(()->{
phone.hello();
},"B").start();
}
}
class Phone2{
//synchronized 锁的对象是方法的调用者
//两个方法用的是同一个锁,谁先拿到谁先执行
public synchronized void sendSms(){
try {
TimeUnit.SECONDS.sleep(4);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("发短信");
}
public synchronized void call(){
System.out.println("打电话");
}
//这里没有锁!不是同步方法,不受锁的影响
public void hello(){
System.out.println("hello");
}
}
2.2标准情况下,两个对象两个线程先打印hello 还是打电话 1.hello 2.发短信
/**
* 8锁,就是关于锁的8个问题
* 1.标准情况下,两个线程先打印发短信 还是打电话 1.打电话 2.发短信
*/
public class Test2 {
public static void main(String[] args) {
Phone2 phone1 = new Phone2();
Phone2 phone2 = new Phone2();
new Thread(()->{
phone1.sendSms();
},"A").start();
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(()->{
phone2.call();
},"B").start();
}
}
class Phone2{
//synchronized 锁的对象是方法的调用者
//两个方法用的是同一个锁,谁先拿到谁先执行
public synchronized void sendSms(){
try {
TimeUnit.SECONDS.sleep(4);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("发短信");
}
public synchronized void call(){
System.out.println("打电话");
}
//这里没有锁!不是同步方法,不受锁的影响
public void hello(){
System.out.println("hello");
}
}
3.2标准情况下,两个对象两个线程先打印hello 还是打电话 1.hello 2.发短信
**
* 8锁,就是关于锁的8个问题
* 5.两个静态方法,两个线程先打印发短信 还是打电话 1.打电话 2.发短信
*/
public class Test3 {
public static void main(String[] args) {
Phone3 phone1 = new Phone3();
Phone3 phone2 = new Phone3();
new Thread(()->{
phone1.sendSms();
},"A").start();
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(()->{
phone2.call();
},"B").start();
}
}
class Phone3{
//synchronized 锁的对象是方法的调用者
//两个方法用的是同一个锁,谁先拿到谁先执行
public static synchronized void sendSms(){
try {
TimeUnit.SECONDS.sleep(4);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("发短信");
}
public static synchronized void call(){
System.out.println("打电话");
}
}
3.3标准情况下,一个对象一个静态方法和一个普通方法先打印发短信 还是打电话 1.打电话2.发短信
/**
* 8锁,就是关于锁的8个问题
* 5.两个方法,两个线程先打印发短信 还是打电话 1.打电话 2.发短信
*/
public class Test4 {
public static void main(String[] args) {
Phone4 phone = new Phone4();
new Thread(()->{
phone.sendSms();
},"A").start();
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(()->{
phone.call();
},"B").start();
}
}
class Phone4{
//synchronized 锁的对象是方法的调用者
//静态的同步方法,锁的是Class 类模板
public static synchronized void sendSms(){
try {
TimeUnit.SECONDS.sleep(4);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("发短信");
}
// 普通方法,锁的是调用者
public synchronized void call(){
System.out.println("打电话");
}
}
3.3标准情况下,两个对象一个静态方法和一个普通方法先打印发短信 还是打电话 1.打电话2.发短信
/**
* 8锁,就是关于锁的8个问题
* 6.两个方法,两个线程先打印发短信 还是打电话 1.打电话 2.发短信
*/
public class Test4 {
public static void main(String[] args) {
Phone4 phone1 = new Phone4();
Phone4 phone2 = new Phone4();
new Thread(()->{
phone1.sendSms();
},"A").start();
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(()->{
phone2.call();
},"B").start();
}
}
class Phone4{
//synchronized 锁的对象是方法的调用者
//普通方法锁的是调用对象
//静态的同步方法,锁的是Class 类模板,而一个类,只有一个类模板
public static synchronized void sendSms(){
try {
TimeUnit.SECONDS.sleep(4);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("发短信");
}
// 普通方法,锁的是调用者
public synchronized void call(){
System.out.println("打电话");
}
}
7.集合类不安全
7.1.list,CopyOnWriteArrayList
7.2.set,CopyOnWriteArraySet
7.3.Map,ConcurrentHashMap
8.Callable
9.常用的辅助类
9.1.CountDownLatch
9.2.CyclicBarrier
9.3.Semaphore
10.读写锁.ReadWriteLock
public class ReadWriteLockDemo {
public static void main(String[] args) {
MyCacheLock myCache = new MyCacheLock();
//写入
for (int i = 1; i <=5; i++) {
final int temp=i;
new Thread(()->{
myCache.put(temp+"",temp+"");
},String.valueOf(i)).start();
}
//读取
for (int i = 1; i <=5; i++) {
final int temp=i;
new Thread(()->{
myCache.get(temp+"");
},String.valueOf(i)).start();
}
}
}
//加锁的
class MyCacheLock{
private volatile Map<String,Object> map=new HashMap<>();
//读写锁,更加细粒度的控制
private ReadWriteLock readWriteLock=new ReentrantReadWriteLock();
//存,写的时候,只希望只有一个线程写
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);
Object o = map.get(key);
System.out.println(Thread.currentThread().getName()+"读取OK");
} catch (Exception e) {
e.printStackTrace();
} finally {
readWriteLock.readLock().unlock();
}
}
}
/**
* 自定义缓存
*/
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);
Object o = map.get(key);
System.out.println(Thread.currentThread().getName()+"读取OK");
}
}
11.阻塞队列
1.add(),remove()
2.offer(),poll()
> 3.put(),take()
> 4.offer(时间),poll(时间)
11.SynchronousQueue 同步队列
public class SynchronousQueueDemo {
public static void main(String[] args) {
BlockingQueue<String> blockingQueue= new SynchronousQueue<>();//同步队列
new Thread(()->{
try{
System.out.println(Thread.currentThread().getName()+"put 1");
blockingQueue.put("1");
System.out.println(Thread.currentThread().getName()+"put 2");
blockingQueue.put("2");
System.out.println(Thread.currentThread().getName()+"put 3");
blockingQueue.put("3");
}catch (Exception e){
e.printStackTrace();
}
},"T1").start();
new Thread(()->{
try{
TimeUnit.SECONDS.sleep(3);
System.out.println(Thread.currentThread().getName()+" get:"+blockingQueue.take());
TimeUnit.SECONDS.sleep(3);
System.out.println(Thread.currentThread().getName()+" get:"+blockingQueue.take());
TimeUnit.SECONDS.sleep(3);
System.out.println(Thread.currentThread().getName()+" get:"+blockingQueue.take());
}catch (Exception e){
e.printStackTrace();
}
},"T2").start();
}
}
12.线程池(重点)
三大方法
public class Demo01 {
public static void main(String[] args) {
//ExecutorService threadPool = Executors.newSingleThreadExecutor();//单个线程
//ExecutorService threadPool = Executors.newFixedThreadPool(5);//创建一个固定的线程池大小
ExecutorService threadPool = Executors.newCachedThreadPool();
try{
for (int i = 1; i <=100; i++) {
threadPool.execute(()->{
System.out.println(Thread.currentThread().getName()+",ok");
});
}
}catch (Exception e){
e.printStackTrace();
}finally {
threadPool.shutdown();
}
}
}
7大参数
分析源码
public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>()));
}
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
Executors.defaultThreadFactory(), defaultHandler);
}
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler) {
if (corePoolSize < 0 ||
maximumPoolSize <= 0 ||
maximumPoolSize < corePoolSize ||
keepAliveTime < 0)
throw new IllegalArgumentException();
if (workQueue == null || threadFactory == null || handler == null)
throw new NullPointerException();
this.corePoolSize = corePoolSize;
this.maximumPoolSize = maximumPoolSize;
this.workQueue = workQueue;
this.keepAliveTime = unit.toNanos(keepAliveTime);
this.threadFactory = threadFactory;
this.handler = handler;
}
public class Demo01 {
public static void main(String[] args) {
/*ExecutorService threadPool = Executors.newSingleThreadExecutor();//单个线程
ExecutorService threadPool2 = Executors.newFixedThreadPool(5);//创建一个固定的线程池大小
ExecutorService threadPool3 = Executors.newCachedThreadPool();*/
ExecutorService threadPool = new ThreadPoolExecutor(
2,
5,
3,
TimeUnit.SECONDS,
new LinkedBlockingDeque<>(3),//候客区3个
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.AbortPolicy());//银行满了,还有人进来,不处理这个人的,抛出异常
//CallerRunsPolicy 哪来的,去哪里
try{
//最大承载: Deque + max
//超过: java.util.concurrent.RejectedExecutionException
for (int i = 1; i <=9; i++) {
threadPool.execute(()->{
System.out.println(Thread.currentThread().getName()+",ok");
});
}
}catch (Exception e){
e.printStackTrace();
}finally {
threadPool.shutdown();
}
}
}
四大拒绝策略
> 小结和拓展
问题:最大线程到底如何定义
13.四大函数式接口(必需掌握)
13.1.四大函数式接口Function
13.2.四大函数式接口Predicate
13.3.四大函数式接口Consumer,消费型接口
13.3.四大函数式接口Supplier,供给型接口
14.Stream流式计算
15.ForkJoin
16.ForkJoin
ForkJoin
public class ForkJoinDemo extends RecursiveTask<Long> {
private Long start;
private Long end;
private Long temp=10000L;
public ForkJoinDemo(Long start, Long end) {
this.start = start;
this.end = end;
}
//计算方法
@Override
protected Long compute() {
if((end-start)<temp){
Long sum=0L;
for (Long i = start; i <end ; i++) {
sum+=i;
}
return sum;
}else{ //forkjoin
long middle=(start+end)/2;
ForkJoinDemo task1 = new ForkJoinDemo(start, middle);
task1.fork();
ForkJoinDemo task2 = new ForkJoinDemo(middle+1, end);
task2.fork();
return task1.join()+task2.join();
}
}
}
测试代码
public class Test {
public static void main(String[] args) throws ExecutionException, InterruptedException {
//test1();//时间:5289
//test2();//时间:3533
test3(); //时间:155
}
public static void test1(){
Long sum=0L;
long start=System.currentTimeMillis();
for (Long i = 0L; i <=10_0000_0000 ; i++) {
sum+=i;
}
long end=System.currentTimeMillis();
System.out.println("sum="+sum+" 时间:"+(end-start));
}
//会使用ForkJoin
public static void test2() throws ExecutionException, InterruptedException {
long start=System.currentTimeMillis();
ForkJoinPool forkJoinPool = new ForkJoinPool();
ForkJoinDemo task = new ForkJoinDemo(0L,10_0000_0000L);
ForkJoinTask<Long> submit = forkJoinPool.submit(task);
Long sum = submit.get();
long end=System.currentTimeMillis();
System.out.println("sum="+sum+" 时间:"+(end-start));
}
//会使用ForkJoin
public static void test3() throws ExecutionException, InterruptedException {
long start=System.currentTimeMillis();
//Stream并行流
long sum = LongStream.rangeClosed(0L, 10_0000_0000L).parallel().reduce(0, Long::sum);
long end=System.currentTimeMillis();
System.out.println("sum="+sum+" 时间:"+(end-start));
}
}
16.异步回调
public class Demo01 {
public static void main(String[] args) throws ExecutionException, InterruptedException {
//发起一个请求
//没有返回值的runAsync异步回调
/* CompletableFuture<Void> completableFuture = CompletableFuture.runAsync(() -> {
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "runAsync=>Void");
});
System.out.println("1111");
completableFuture.get(); //获取阻塞执行的结果*/
CompletableFuture<Integer> completableFuture = CompletableFuture.supplyAsync(()->{
System.out.println(Thread.currentThread().getName() + "supplyAsync=>Integer");
//int i=10/0;
return 1024;
});
System.out.println(completableFuture.whenComplete((t, u) -> {
System.out.println("t=>" + t);//正常的返回结果
System.out.println("u=>" + u);//错误信息
}).exceptionally((e) -> {
System.out.println(e.getMessage());
return 233;//可以获取到错误的返回结果
}).get());
}
}
16.JMM
public class JMMDemo {
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);
}
}
public class VDemo02 {
//volatile不保证原子性
private volatile static 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 = 0; j < 1000; j++) {
add();
}
}).start();
}
while(Thread.activeCount()>2){//main jc
Thread.yield();
}
System.out.println(Thread.currentThread().getName()+":"+num);
}
}
public class VDemo02 {
//volatile不保证原子性
//AtomicInteger 是一个原子性的integer
private volatile static AtomicInteger num=new AtomicInteger();
public static void add(){
//num++; //不是一个原子性操作
num.getAndIncrement();//AtomicInteger +1 方法 CAS
}
public static void main(String[] args) {
for (int i = 1; i <=20; i++) {
new Thread(()->{
for (int j = 0; j < 1000; j++) {
add();
}
}).start();
}
while(Thread.activeCount()>2){//main jc
Thread.yield();
}
System.out.println(Thread.currentThread().getName()+":"+num);
}
}
17.彻底玩转单例模式
饿汉式
public class Hungry {
//可能会浪费空间
private byte[] data1=new byte[1024*1024];
private byte[] data2=new byte[1024*1024];
private byte[] data3=new byte[1024*1024];
private byte[] data4=new byte[1024*1024];
private Hungry(){
}
private final static Hungry HUNGRY=new Hungry();
public static Hungry getInstance(){
return HUNGRY;
}
}
//懒汉式单例
public class LazyMan {
private LazyMan(){
synchronized (LazyMan.class){
if(lazyMan!=null){
throw new RuntimeException("不要试图使用反射破坏异常");
}
}
System.out.println(Thread.currentThread().getName()+"ok");
}
private volatile static LazyMan lazyMan;
//双重检测锁模式的 懒汉式单例 DCL懒汉式
private static LazyMan getInstance(){
if(lazyMan==null) {
synchronized (LazyMan.class) {
if (lazyMan == null) {
lazyMan = new LazyMan();
}
}
}
return lazyMan;
}
//反射
public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
LazyMan instance = LazyMan.getInstance();
Constructor<LazyMan> declaredConstructor = LazyMan.class.getDeclaredConstructor(null);
declaredConstructor.setAccessible(true);
//LazyMan instance = declaredConstructor.newInstance();
LazyMan instance2 = declaredConstructor.newInstance();
System.out.println(instance);
System.out.println(instance2);
}
}
静态内部类
在这里插入代码片
单例不安全,反射
枚举
如果两个都是通过反射来创建的
反编译.class文件命令
使用jad,把我们的源码变成.java文件
//enum 是一个什么?本身是一个Class类
public enum EnumSingle{
INSTANCE;
public EnumSingle getInstance(){
return INSTANCE;
}
}
class Test{
//反射
public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
//LazyMan instance = LazyMan.getInstance();
EnumSingle instance1=EnumSingle.INSTANCE;
Constructor<EnumSingle> declaredConstructor = EnumSingle.class.getDeclaredConstructor(String.class,int.class);
declaredConstructor.setAccessible(true);
EnumSingle instance2 = declaredConstructor.newInstance();
System.out.println(instance1);
System.out.println(instance2);
}
}
18.深入理解CAS
ABA问题
public class CASDemo {
public static void main(String[] args) {
//CAS compareAndSet:比较并交换
// 期望,更新
// 如果我期望的值达到了,那么就更新,否则,就不更新,CAS是CPU的并发原语
AtomicInteger atomicInteger = new AtomicInteger(2020);
//=======================捣乱的线程============================
System.out.println(atomicInteger.compareAndSet(2020, 2021));
System.out.println(atomicInteger.get());
System.out.println(atomicInteger.compareAndSet(2021, 2020));
System.out.println(atomicInteger.get());
//======================期望的线程============================
System.out.println(atomicInteger.compareAndSet(2020, 6666));
System.out.println(atomicInteger.get());
}
}
19.原子引用
public class CASDemo {
//CAS compareAndSet:比较并交换
// 期望,更新
// 如果我期望的值达到了,那么就更新,否则,就不更新,CAS是CPU的并发原语
//AtomicStampedReference 注意,如果泛型是一个包装类,注意对象的引用问题
//正常在业务操作,这里面比较的都是一个个对象
static AtomicStampedReference<Integer> atomicStampedReference = new AtomicStampedReference<>(1,1);
public static void main(String[] args) {
new Thread(()->{
int stamp = atomicStampedReference.getStamp();//获得版本号
System.out.println("a1=>"+stamp);
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(atomicStampedReference.compareAndSet(1, 2,
atomicStampedReference.getStamp(), atomicStampedReference.getStamp() + 1));
System.out.println("a2=>"+atomicStampedReference.getStamp());
System.out.println(atomicStampedReference.compareAndSet(2, 1,
atomicStampedReference.getStamp(), atomicStampedReference.getStamp() + 1));
System.out.println("a3=>"+atomicStampedReference.getStamp());
},"a").start();
new Thread(()->{
int stamp = atomicStampedReference.getStamp();//获得版本号
System.out.println("b1=>"+stamp);
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(atomicStampedReference.compareAndSet(1, 6,
stamp, stamp + 1));
System.out.println("b2=>"+atomicStampedReference.getStamp());
},"b").start();
}
}
20.各种锁的理解
20.1.公平锁,非公平锁
20.2.可重入锁
synchronized版
// synchronized
public class Demo01 {
public static void main(String[] args) {
Phone phone = new Phone();
new Thread(()->{
phone.sms();
},"A").start();
new Thread(()->{
phone.sms();
},"B").start();
}
}
class Phone{
public synchronized void sms(){
System.out.println(Thread.currentThread().getName()+":sms");
call(); //这里也有锁
}
public synchronized void call() {
System.out.println(Thread.currentThread().getName()+":call");
}
}
lock版
// Lock
public class Demo02 {
public static void main(String[] args) {
Phone2 phone = new Phone2();
new Thread(()->{
phone.sms();
},"A").start();
new Thread(()->{
phone.sms();
},"B").start();
}
}
class Phone2{
Lock lock=new ReentrantLock();
public void sms(){
lock.lock();
try {
System.out.println(Thread.currentThread().getName()+":sms");
call(); //这里也有锁
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public void call() {
lock.lock();
try {
System.out.println(Thread.currentThread().getName()+":call");
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
20.3.自旋锁
我们来自定义一个锁来测试
public class SpinlockDemo {
//int 0
//Thread null
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 myUnLock(){
Thread thread = Thread.currentThread();
System.out.println(Thread.currentThread().getName()+"==> myUnlock");
atomicReference.compareAndSet(thread,null);
}
}
测试类:
public class TestSpinlock {
public static void main(String[] args) throws InterruptedException {
SpinlockDemo lock = new SpinlockDemo();
new Thread(()->{
lock.myLock();
try {
TimeUnit.SECONDS.sleep(3);
} catch (Exception e) {
e.printStackTrace();
}finally {
lock.myUnLock();
}
},"T1").start();
TimeUnit.SECONDS.sleep(1);
new Thread(()->{
lock.myLock();
try {
TimeUnit.SECONDS.sleep(3);
} catch (Exception e) {
e.printStackTrace();
}finally {
lock.myUnLock();
}
},"T2").start();
}
}
20.4.死锁
死锁是什么
> 死锁测试,怎么去分析死锁
public class DeadLockDemo {
public static void main(String[] args) {
String lockA="lockA";
String lockB="lockB";
new Thread(new MyThread(lockA,lockB),"T1").start();
new Thread(new MyThread(lockB,lockA),"T2").start();
}
}
class MyThread implements Runnable{
private String lockA;
private String lockB;
public MyThread(String lockA, String lockB) {
this.lockA = lockA;
this.lockB = lockB;
}
@Override
public void run() {
synchronized (lockA){
System.out.println(Thread.currentThread().getName()+"lock"+lockA+"=>get"+lockB);
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (lockB) {
System.out.println(Thread.currentThread().getName()+"lock"+lockB+"=>get"+lockA);
}
}
}
}