首页 > 其他分享 >JUC-3

JUC-3

时间:2023-10-06 17:11:42浏览次数:26  
标签:JUC Thread System println new public out

JUC-3

13、Stream流式计算

什么是Stream流式计算

  • 大数据∶存储+计算
  • 集合、MySQL本质就是存储东西的﹔
  • 计算都应该交给流来操作!

14、ForkJoin

什么是ForkJoin

ForkJoin在JDK 1.7,并行执行任务!提高效率。大数据量!

大数据:Map Reduce (把大任务拆分为小任务)

image-20230927121559091

ForkJoin特点:工作窃取(a线程完成帮b完成最后一部分)

这个里面维护的都是双端队列

    @Test
    public void test1(){
    long sum=0l;
    long start=System.currentTimeMillis();
        for (int i = 1; i <= 10_0000_0000; i++) {
            sum+=i;
        }
        long end=System.currentTimeMillis();
        System.out.println("sum= "+sum+"  time= "+(end-start));//289
    }

   //并行流
    @Test
    public void test2(){
        long start=System.currentTimeMillis();
        long sum= LongStream.rangeClosed(0l,10_0000_0000l).parallel().reduce(0,Long::sum);//sum();
        //返回有序顺序 IntStream从 startInclusive (含)至 endInclusive通过的递增步长(含) 1 。
        //可以使用for循环顺序地产生递增值的等效序列,如下所示:
        //   for (int i = startInclusive; i <= endInclusive ; i++) { ... }
        long end=System.currentTimeMillis();
        System.out.println("sum= "+sum+"  time= "+(end-start));//195   187

    }

15、异步回调

Future设计的初衷:对将来的某个事件的结果进行建模

  • Future计算的结果。 提供方法来检查计算是否完成,等待其完成,并检索计算结果。 结果只能在计算完成后使用方法get进行检索,如有必要,阻塞,直到准备就绪。
@Test
    public void test3() throws ExecutionException, InterruptedException {
    CompletableFuture<Void> runAsync = CompletableFuture.runAsync(() -> {
        try {
            TimeUnit.SECONDS.sleep(2);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        System.out.println(Thread.currentThread().getName()+"  000");
    });
    System.out.println("11111111");
    runAsync.get();//获取阻塞执行结果

}

16、JMM

什么是JMM
JMM : Java内存模型,不存在的东西,概念!约定!

关于JMM的一些同步的约定︰

1、线程解锁前,必须把共享变量立刻刷回主存。

2、线程加锁前,必须读取主存中的最新值到工作内存中!

3、加锁和解锁是同一把锁

线程工作内存、主内存
8种操作:

image-20230927171024353

问题,线程B修改了值,但是线程A不能及时可见

17、Volatile

请你谈谈你对Volatile的理解

Volatile是Java虚拟机提供轻量级的同步机制

1、保证可见性

public class Day92700  {
    //不加vo1atile程序就会死循环!
    // 加volatile 可以保证可见性
    volatile static int num=0;

    public static void main(String[] args) {
        new Thread(()->{
            while (num==0){

            }
        }).start();
        try {
            TimeUnit.SECONDS.sleep(2);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        num=1;
        System.out.println(num);
    }

2、不保证原子性

原子性:不可分割
线程A在执行任务的时候,不能被打扰的,也不能被分割。要么同时成功,要么同时失败。

如果不加lock和synchronized,怎么样保证原子性

使用原子类,解决原子性问题

/ / volatile不保证原子性/原子类的Integer
private volatile static AtomicInteger num = new AtomicInteger();
public static void add(i
 / num++;(/不是一个原子性操作
num.getAndIncrement(); l/ AtomicInteger + 1方法,CAS
}
public static void main( String[] args) {
/理论上num结果应该为2万
for (int i = 1; i <= 20; i++) {
new Thread(()->i
for (int j = ; j < 1000 ; j++) {
add();
}
}).start();
}

这些类的底层都直接和操作系统挂钩! 在内存中修改值!Unsafe类是一个很特殊的存在!

3、禁止指令重排

什么是指令重排:

你写的程序,计算机并不是按照你写的那样去执行的。

源代码-->编译器优化的重排-->指令并行也可能会重排-->内存系统也会重排--->执行

处理器在进行指令重排的时候,考虑:数据之间的依赖性!

image-20230927174155178

非计算机专业

volatile可以避免指令重排:内存屏障。CPU指令。作用:

1、保证特定的操作的执行顺序!

2、可以保证某些变量的内存可见性(利用这些特性volatile实现了可见性)

18、彻底玩转单例模式

//懒汉式单例
public class LazyMan i
private LazyMan()i
system.out.println(Thread.currentThread( ).getName( ) + "ok");

private volatile static LazyMan LazyMan;
/双重检测锁模式的懒汉式单例DCL懒汉式
    public static LazyMan getInstance()i
if (LazyMan==nu11)i
synchronized (LazyMan.class){
if (LazyMan==nu11){
LazyMan = new LazyMan(); //不是—个原子性操作**
*1.分配内存空间
* 2、执行构造方法,初始化对象*
    3、把这个对象指向这个空间*
*123*132A
*B [/此时LazyMan还没有完成构造*入
}
I
}
}
return lazyMan;
}

单例不安全,反射

枚举

枚举类型可以取代以往常量的定义方式,即将常量封装在类或接口中。此外,枚举类型还提供了安全检查功能。枚举类型本质上还是以类的形式存在。

1、使用枚举类型设置常量
以往设置常量,通常将常量放置在接口中,这样在程序中就可以直接使用了,并且该常量不能被修改,因为在接口中定义的常量时,该常量的修饰符为final与static。

19、深入理解CAS

public class Day10500 {
    public static void main(String[] args) {
        // CAScompareAndSet :比较并交换!
        AtomicInteger atomicInteger = new AtomicInteger(2020);
        //期望、更新
       // public final boolean compareAndSet(int expect, int update)/
        // 如果我期望的值达到了,那么就更新,否则,就不更新
        atomicInteger.compareAndSet(2020,2023);
        System.out.println(atomicInteger.get());//2023
    }
}

image-20231005152651028

Java无法操作内存
Java可以调用c++ native

C++可以操作内存
Java的后门.可以通过unsafe这个类操作内存

image-20231005152823421

image-20231005152950488

CAS∶比较当前工作内存中的值和主内存中的值,如果这个值是期望的,那么则执行操作!如果不是就一直循环!

缺点∶

1、循环会耗时
2、一次性只能保证一个共享变量的原子性3、ABA问题

CAS : ABA问题(狸猫换太子)

image-20231005182550948

20、原子引用

7.【强制】所有的相同类型的包装类对象之间值的比较,全部使用equals方法比较。
说明:对于Integer var = ?在-128至127之间的赋值,Integer对象是在
IntegerCache. cache产生,会复用己有对象,这个区间内的Integer值可以直接使用==进行判断,但是这个区间之外的所有数据,都会在堆上产生,并不会复用已有对象,这是一个大坑,推荐使用equals方法进行判断。

带版本号的原子操作!

package demo05;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicStampedReference;

public class Day10502 {
    public static void main(String[] args) {
        //’正常在业务操作,这里面比较的都是—个个对象
        AtomicStampedReference<Integer> reference = new AtomicStampedReference<>(0, 1);
            //AtomicStampedReference 注意,如果泛型是一个包装类,注意对象的引用问题

        new Thread(()->{
            int stamp=reference.getStamp();//获得版本号
            System.out.println("a1=>"+stamp);

            try {
                TimeUnit.SECONDS.sleep(3);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }

            System.out.println(reference.compareAndSet(0, 1, reference.getStamp(), reference.getStamp() + 1));
            System.out.println("a2=>"+reference.getStamp());

            System.out.println(reference.compareAndSet(1, 0, reference.getStamp(), reference.getStamp() + 1));
            System.out.println("a3=>"+reference.getStamp());
        },"a").start();

        ///乐观锁的原理相同!
        new Thread(()->{
            int stamp=reference.getStamp();//获得版本号
            System.out.println("b1=>"+stamp);
            try {
                TimeUnit.SECONDS.sleep(2);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }

            System.out.println(reference.compareAndSet(0, 6, stamp, stamp + 1));
            System.out.println("b2=>"+reference.getStamp());
        },"b").start();

    }
}

21、各种锁的理解

1、公平锁、非公平锁

  • 公平锁:非常公平,不能够插队,必须先来后到!
  • 非公平锁:非常不公平,可以插队(默认都是非公平)

2、可重入锁

image-20231006123754171

synchronized

class Phone{
public synchronized void sms ({
system.out.println(Thread.currentThread(). getName() + "sms ");ca11();//这里也有锁
}
public synchronized void ca11o{
system. out.print1n(Thread.currentThread(). getName() + "ca17");
}
}

lock

class Phone2{
Lock lock = new ReentrantLock();
public void sms(){
lock.lock();//细节问题: Lock.Lock( ); lock .unLock(); 
    // lock锁必须配对,否则就会死在里面lock . lock();
try {i
System.out.println(Thread.currentThread().getName() + "sms" );call();//这里也有锁
catch (Exception e){
e.printstackTrace();}finally i
lock.unlock();lock.unlock();

3、自旋锁

package demo05;


import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;

//自旋锁
public class Day10600 {
    AtomicReference<Thread> atomicReference=new AtomicReference<>();

    //加锁
    public void mylock(){
        Thread thread=Thread.currentThread();
        System.out.println(thread.getName()+"---mylock");

        //自旋锁
        while (!atomicReference.compareAndSet(null,thread)){

        }
    }

    //解锁
    public void myunlock(){
        Thread thread = Thread.currentThread();
        System.out.println(thread.getName()+"---myunlock");
        atomicReference.compareAndSet(thread,null);
    }

    public static void main(String[] args) throws InterruptedException {
        Day10600 day10600 = new Day10600();
        new Thread(()->{
            day10600.mylock();
            try {
                TimeUnit.SECONDS.sleep(4);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }finally {
                day10600.myunlock();
            }

        },"aa").start();
        TimeUnit.SECONDS.sleep(1);
         
        new Thread(()->{
            day10600.mylock();
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }finally {
                day10600.myunlock();
            }

        },"bb").start();

    }
}

aa---mylock
bb---mylock
aa---myunlock
bb---myunlock

4、死锁

image-20231006131933540

解决问题

1、使用jps -1定位进程号

2、使用 jstack查看进行信息

面试,工作中!排查问题:

1、日志
2、堆栈

标签:JUC,Thread,System,println,new,public,out
From: https://www.cnblogs.com/xin-zhi-suo-xiang/p/17744729.html

相关文章

  • JUC工具类CountDownLatch、CyclicBarrier、Semaphore介绍
    CountDownLatch:它是一种同步工具,用于控制一个或多个线程等待其他线程完成操作后再继续执行。它的作用是让某个线程等待一组操作执行完成,再继续执行自己的任务。CountDownLatch内部有一个计数器,当计数器的值为0时,等待的线程将会被唤醒。通过CountDownLatch的构造函数可以指定计......
  • 一点点JUC的小姿势
    1JUCJUC就是java.util.concurrent下面的类包,专门用于多线程的开发。1.1并发与并行并发多线程操作同一个资源。CPU只有一核,模拟出来多条线程,天下武功,唯快不破。那么我们就可以使用CPU快速交替,来模拟多线程。并发编程的本质:充分利用CPU的资源!并行并行:多个人一起行......
  • JUC并发编程---Lock锁
    文章目录什么是Locksynchronized加锁和Lock加锁代码示例synchronized使用Lock加锁公平锁和非公平锁公平锁:非公平锁:Lock和Synchronized的区别synchronized版的生产者和消费者Lock版的生产者和消费者生产者和消费者出现的问题Condition精准通知和唤醒线程什么是Lock官网介绍:虽然......
  • JUC-2
    JUC-26、集合类不安全listpackagedemo02;importjava.util.*;importjava.util.concurrent.CopyOnWriteArrayList;//.ConcurrentModificationException并发修改异常publicclassDay92300{publicstaticvoidmain(String[]args){/*并发下Ar......
  • JUC-1
    JUC-11、什么是JUC源码+官方文档面试高频问!java.util工具包、包、分类业务∶普通的线程代码ThreadRunnable没有返回值、效率相比入Callable相对较低!2、线程和进程线程、进程,如果不能使用一句话说出来的技术,不扎实!进程:—个程序,QQ.exeMusic.exe程序的集合;一个进程往......
  • 全网最详细Java-JUC
    Java-JUC⓪基础❶进程&线程进程:指一个内存中运行的应用程序,每个进程都有自己独立的一块内存空间。线程:比进程更小的执行单位,一个进程可以启动多个线程,每条线程并行执行不同的任务。❷并行&并发并行(Parallel):在同一时刻,有多个指令在多个CPU上同时执行。并发(Concurrent):在......
  • 25届实习秋招-Java面试-JUC多线程面试题整理-牛客网
    JUC介绍一下JUC下的锁(如何使用及应用场景)线程什么是进程:特征什么是线程:资源为什么多线程,什么使用用单线程,什么时候多线程,什么条件下多线程快。进程和线程的对比:进程如何通信,每种通信存放的介质。||线程的通信,几种方式。join进程和线程的区别,在JVM层面的体现一......
  • Java多线程____JUC并发锁机制
    1.同步锁即通过synchronized关键字来进行同步,实现对竞争资源的互斥访问的锁。同步锁的原理是,对于每一个对象,有且仅有一个同步锁;不同的线程能共同访问该同步锁但是,在同一个时间点,该同步锁能且只能被一个线程获取到。这样,获取到同步锁的线程就能进行CPU调度,从而在CPU上执行;而没有获......
  • JUC并发编程
    JUC并发编程1.什么是JUCjava.util工具包,包,分类业务:普通的线程代码ThreadRunable没有返回值,效率相比Callable相对较低!2.线程和进程线程、进程、如果不能使用一句话说出来的技术,不扎实!进程:一个程序,例如qq.exe,代表一个程序的集合一个进程往往包含多个线程,而一个进......
  • JUC
    一、JUC1.概念从Java5开始,在JDK中多出了java.util.concurrent包(简称:JUC)。JUC主要是让开发者在多线程编程中更加简单、方便一些。通过JDK内置了一些类、接口、关键字,补充完善了JDK对于并发编程支持的“短板”。2.主要包含功能Executor:线程池Atomic:原子操......