前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >多线程进阶

多线程进阶

作者头像
Dean0731
发布于 2021-03-05 03:17:10
发布于 2021-03-05 03:17:10
29700
代码可运行
举报
文章被收录于专栏:blog-技术博客blog-技术博客
运行总次数:0
代码可运行

线程与进程

  • java默认2个线程,main,gc
  • 真实的线程时底层C++调用的,并不是java
  • cup核心数,就是并行的线程数
  • 单核CUP,要多线程并行,就是用并发实现宏观并行
  • 线程状态
    • New
    • running
    • blocked
    • waiting
    • time_waiting
    • terminal
  • wait与sleep
    • 来自不同的类
    • 都会释放cup,但wait释放锁,即释放资源,sleep不释放
    • wait只在同步代码块,sleep任意
  • 线程是一个资源类,没有任何附属操作,OOP编程
    • 资源类包含属性,方法
    • 资源类方法同步
    • 启动线程操作资源类

集合安全

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
List<Integer> 1 = new ArrayList<>();
List<Integer> l = new Vector<>(); // 同步sync
List<Integer> l = Collections.synchronizedList(new ArrayList<>()); // 同步sync
List<Integer> l = new CopyOnWriteArrayList<>(); // Lock锁 JUC里面的

Set<Integer> s = new HashSet<>(); // 就是hashmap的键
Set<Integer>  s= Collections.synchronizedSet(new HashSet<>());// 同步sync
Set<Integer>  s= new CopyOnWriteArraySet<>();// Lock 锁 JUC里面的


// -----------------------------
Map<String,String> map = new HashMap<String,String>(16,0.75f);
Map<String,String> map2 = new Hashtable<>();// 同步sync
Map<String,String> map = Collections.synchronizedMap(new HashMap<>());// 同步sync
Map<String,String> map = new ConcurrentHashMap<>();//分段Lock锁,锁定某一段 JUC里面的

阻塞队列

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//BlockingQueue 实现类都是用了Lock的,即线程安全的
BlockingQueue<Integer> q = new ArrayBlockingQueue<Integer>(10);
BlockingQueue<Integer> q = new LinkedBlockingDeque<Integer>();
// 同步队列,只能存放一个元素
BlockingQueue<Integer> q = new SynchronousQueue<Integer>();
BlockingQueue<Integer> q = (BlockingQueue<Integer>) new ConcurrentLinkedQueue<Integer>();

线程池

  • 节约资源
  • 控制最大并发数
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 本质就是ThreadPoolExecutor(7各参数)
Executors.newSingleThreadExecutor();
Executors.newFixedThreadPool(5);
Executors.newCachedThreadPool();
// 推荐手动创建
ExecutorService s = new ThreadPoolExecutor(
    2, // 一直开着的上数量
    Runtime.getRuntime().availableProcessors(),// 最大线程数,一般就是CUP核心数
    3, // 等待
    TimeUnit.SECONDS, // 单位
    new LinkedBlockingDeque<>(3),// 等待队列 最多同时开启max+cap个线程
    Executors.defaultThreadFactory(), // 默认线程工厂
    // 拒绝策略,有四种
    //new ThreadPoolExecutor.AbortPolicy() //线程超过max+cap,又来任务,抛出异常
    //new ThreadPoolExecutor.CallerRunsPolicy() //线程超过max+cap,线程池不受理,来源线程执行
    //new ThreadPoolExecutor.DiscardPolicy() //线程超过max+cap,又来任务,不抛出异常,但丢弃任务
    new ThreadPoolExecutor.DiscardOldestPolicy() //线程超过max+cap,又来任务,尝试与第一个任务竞争,竞争失败,不抛异常,但还丢弃任务

函数式接口,简化编程模型

Stream流计算

  • 数据------》存储,计算
    • 集合,mysql用于存储
    • 计算都是流
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
        List<String> l = new ArrayList<>();
        l.stream()
                .filter(str->{return str.length()>=2;}) // 断定型
                .map(str->{return str.toLowerCase();}) // 转换型
                .sorted((str1,str2)->str1.compareTo(str2)) // 排序
                .limit(1) // 只输出1个
                .forEach(System.out::println);

ForkJoin

  • 并行执行任务
  • 大量数据使用
    • forkjoinpool
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class ForkJoinDemo extends RecursiveTask<Long>{
    private Long start;
    private Long end;
    private Long temp=100000L; // 临界值

    public ForkJoinDemo(){

    }
    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{
            Long mid = (start + end)/2;
            ForkJoinDemo f1 = new ForkJoinDemo(start,mid);
            f1.fork(); //任务压入队列
            ForkJoinDemo f2 = new ForkJoinDemo(mid+1,end);
            f2.fork();
            return f1.join()+f2.join();
        }
    }

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        // 1 加到10亿
        // 方法一 for循环累加
        // 方法二
        ForkJoinPool pool = new ForkJoinPool();
        ForkJoinTask<Long> submit = pool.submit(new ForkJoinDemo(1L,10_0000_0000L));// 提交任务
        System.out.println(submit.get());
        // 方法三 最快
        LongStream.range(0L,10_0000_0000L).parallel().reduce(0,Long::sum);
    }
}

异步回调

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public static void main(String args[]) throws ExecutionException, InterruptedException {
    CompletableFuture<Void> completableFuture = CompletableFuture.runAsync(()->{
        System.out.println("com1执行");// 耗时操作
    });
    System.out.println(completableFuture.get()); // null

    CompletableFuture<Integer> completableFuture2 = CompletableFuture.supplyAsync(()->{
        System.out.println("com2执行");
        return 2; // 有返回值
    });

    completableFuture2.whenComplete((t,u)->{
        System.out.println("t=>"+t); // 正常执行的返回结果
        System.out.println("u=>"+u); // 错误信息
    }).exceptionally((e)->{
        System.out.println(e.getMessage());//
        return 500; // 出错了返回的结果
    });
    System.out.println(completableFuture2.get());

}

JMM

不存在的东西,是一种约定

  • 线程解锁前,把共享变量立刻刷新回主存
  • 加锁前,读取主存最新值到工作内存
  • 加锁,解锁是同一把锁
  • 8种指令成对出现

程序不知道主存中的值被修改了。

Volatile

  • 可见性,上述例子中flag 设置为volatile即可,
  • 不保证原子性,在不使用锁的时候,使用原子类可解决原子性问题
    • 这些原子类与操作系统有关系,在内存中修改值
    • Unsafe类,特殊的存在,java的后门,通过它可以操作内存
  • 禁止指令重排
    • 你的程序,计算机并不是按照你写的执行
    • 源码-》编译器优化重排-》指令并行重排-》内存系统重排-》执行

单例模式

https://blog.dean0731.top/post/8

CAS

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
AtomicInteger num = new AtomicInteger(2020);
// 比较并交换 cup的并发原语,即能直接操作内存
num.compareAndSet(2020,2021);
System.out.println(num.get());
num.getAndIncrement();
  • 比较工作内存与主存中的值,是期望的,执行操作,如果不是,一直循环
    • 循环耗时
    • 一次只能一个共享变量
    • ABA问题

原子引用

带版本号的原子操作

自旋锁

CAS实现自旋锁

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class SpinLock{
    AtomicReference<Thread> f = new AtomicReference<>();
    public void lock(){
        // f 可以说就是当前线程, f为空, f就变为当前线程, 其他线程来拿锁的时候不为空,一直循环
        while(!f.compareAndSet(null,Thread.currentThread())){

        }
    }

    public void unlock(){
        // 释放锁,
        f.compareAndSet(Thread.currentThread(),null);
    }
}

死锁

排查死锁

  • jsp -l 可查看运行中的java程序
  • jstack 进程号 查看该程序的堆栈信息
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021-03-03 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
多线程进阶--JUC并发编程
https://blog.csdn.net/weixin_44502509/article/details/106872957
hhss
2021/02/12
6240
多线程进阶--JUC并发编程
JUC并发编程
业务:普通的线程代码 Thread Runnable: 没有返回值、效率比Callable 相对较低!
JokerDJ
2023/11/27
2910
JUC并发编程
java---多线程[重点(下)]
第三种创建线程的方式,使用Callable创建的线程可以有一个返回值。Interface Callable<V>它是一个接口和Runnable一样。void run() 这方法是一个无返回值,无参数的方法。Callable 提供了一个call()返回可以返回一个值,这个值的类型由Callable<V>泛型决定。
用户10787181
2023/10/17
3040
java---多线程[重点(下)]
JUC并发编程原理精讲(源码分析)
进程:是指一个内存中运行的程序,每个进程都有一个独立的内存空间,一个应用程序可以同时运行多个进程。进程是资源分配的单位。
不吃紫菜
2023/05/07
9260
JUC并发编程原理精讲(源码分析)
杰哥教你面试之一百问系列:java中高级多线程concurrent的使用
提到多线程,当然要熟悉java提供的各种多线程相关的并发包了,而java.util.concurrent就是最最经常会使用到的,那么关于concurrent的面试题目有哪些呢?一起来看看吧。
程序那些事
2023/09/07
3890
JUC系列(七) ForkJion任务拆分与异步回调
常见的两种创建线程的方式。一种是直接继承Thread,另外一种就是实现Runnable接口。
冷环渊
2022/12/03
3230
JUC系列(七) ForkJion任务拆分与异步回调
万字长文扫盲JUC基础
当以上四个条件同时满足时,就有可能导致死锁的发生。死锁是一种难以调试和解决的问题,因此在设计并发程序时需要特别小心,避免引入可能导致死锁的条件。
cheese
2024/01/31
2150
万字长文扫盲JUC基础
深入讲解java多线程与高并发:线程池ThreadPool
今天这节课呢,我们通过一道面试把前面讲的哪些基础复习一下,然后再开始线程池这部分的内容,我们一点一点来看。
愿天堂没有BUG
2022/10/28
4810
深入讲解java多线程与高并发:线程池ThreadPool
Java 实现多线程的n种方法
在现代编程中,多线程是一项关键技术,它使得程序能够同时执行多个任务,提高了系统的效率和性能。在Java中,有多种方法可以实现多线程,每种方法都有其独特的应用场景和优缺点。本文将详细介绍几种常见的Java多线程实现方法,包括基础的Thread类、Runnable接口、高级的线程池、并发工具类、异步编程以及新的并发特性,帮助你深入理解多线程的不同实现方式。
繁依Fanyi
2024/11/22
1850
JUC并发编程(一)多线程使用和线程池
一个进程往往可以包含多个线程,至少包含一个! Java默认有几个线程? 2 个: mian、GC 对于Java而言:Thread、Runnable、Callable 三种实现线程的方式。 JAVA不能开启线程,是调用本地方法,查看start方法可以看到底层是C++来开启线程的
HcodeBlogger
2020/07/14
7350
JUC并发编程(一)多线程使用和线程池
并发编程从入门到放弃系列开始和结束
对于 Java 部分的面试来说,突然想到并发这一块的内容是不太完整的,这篇文章会通篇把多线程和并发都大致阐述一遍,至少能够达到了解原理和使用的目的,内容会比较多,从最基本的线程到我们常用的类会统一说一遍,慢慢看。
艾小仙
2022/09/01
7890
并发编程从入门到放弃系列开始和结束
并发编程- java.util.concurrent用户指南
本指南根据 Jakob Jenkov 最新博客翻译,请随时关注博客更新:http://tutorials.jenkov.com/java-util-concurrent/index.html。 本指南已做成中英文对照阅读版的 pdf 文档,有兴趣的朋友可以去 Java并发工具包java.util.concurrent用户指南中英文对照阅读版.pdf[带书签] 进行下载。
高广超
2018/12/12
1K0
【JUC】009-ForkJoin分支合并、异步回调、JMM、Volatile关键字、指令重排
Java 7开始引入了一种新的Fork/Join线程池,它可以执行一种特殊的任务:把一个大任务拆成多个小任务并行执行;
訾博ZiBo
2025/01/06
900
【JUC】009-ForkJoin分支合并、异步回调、JMM、Volatile关键字、指令重排
JUC学习笔记——并发工具线程池
如果想要解除之前的饥饿现象,正确的方法就是采用Worker Thread模式为他们分配角色,让他们只专属于一份工作:
秋落雨微凉
2022/11/21
4040
JUC学习笔记——并发工具线程池
JUC并发知识_并行与并发
重入锁实现可重入性原理或机制是:每一个锁关联一个线程持有者和计数器,当计数器为 0 时表示该锁没有被任何线程持有,那么任何线程都可能获得该锁而调用相应的方法;当某一线程请求成功后,JVM会记下锁的持有线程,并且将计数器置为 1;此时其它线程请求该锁,则必须等待;而该持有锁的线程如果再次请求这个锁,就可以再次拿到这个锁,同时计数器会递增;当线程退出同步代码块时,计数器会递减,如果计数器为 0,则释放该锁。
全栈程序员站长
2022/09/21
2940
JUC并发知识_并行与并发
JDK中Concurrent包工具类指南
这篇翻译指南很能解决问题,对于初步建立并发包的认识很有帮助,感谢原作者和翻译者 Java 并发工具包 java.util.concurrent 用户指南 本指南根据 Jakob Jenkov 最新博客翻译,请随时关注博客更新:http://tutorials.jenkov.com/java-util-concurrent/index.html。 本指南已做成中英文对照阅读版的 pdf 文档,有兴趣的朋友可以去
于霆霖
2018/05/04
2.5K0
BATJ面试必会之并发篇
调用 Thread.sleep() 方法使线程进入限期等待状态时,常常用“使一个线程睡眠”进行描述。
乔戈里
2019/03/09
6220
JUC并发编程
并发编程是指多个线程同时执行程序的情况。在并发编程中,由于多个线程可能同时访问共享资源,因此需要考虑线程同步、原子性、可见性等问题。
一只
2024/06/26
630
Core Java 并发:理解并发概念
从诞生开始,Java 就支持线程、锁等关键的并发概念。这篇文章旨在为使用了多线程的 Java 开发者理解 Core Java 中的并发概念以及使用方法。
用户1655470
2019/03/06
8240
Core Java 并发:理解并发概念
【进击面试_03】Java 并发
☞ JMM 是什么   JMM(Java 内存模型:Java Memory Model,简称 JMM)本身是一种抽象的概念并不真实存在,它描述的是一组规则或规范,定义了程序中各个共享变量的访问规则,即在虚拟机中将变量存储到内存和从内存读取变量这样的底层细节。   根据 JMM 的设计,系统存在一个主内存(Main Memory),Java 中所有实例变量都储存在主存中,对于所有线程都是共享的。每个线程都有自己的工作内存(Working Memory)是私有数据区域。线程对变量的操作(读取赋值等)必须在工作内存中进行,首先要将变量从主内存拷贝的自己的工作内存空间,然后对变量进行操作,操作完成后再将变量写回主内存,不能直接操作主内存中的变量,各个线程中的工作内存中存储着主内存中的变量副本拷贝。不同的线程间无法访问对方的工作内存,线程间的通信必须通过主内存来完成。
Demo_Null
2021/03/04
2970
【进击面试_03】Java 并发
相关推荐
多线程进阶--JUC并发编程
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文