并发编程(四):深入浅出多线程与线程池

深入浅出Java多线程:从基础到高效并发编程实践 本文从Java多线程的基础概念开始,讲解了线程池的使用、并发问题的解决方案(如锁、原子变量、并发集合等),并深入探讨了如何通过优化策略提升并发性能。掌握这些技术能够帮助你更好地应对复杂的并发编程挑战,提升Java程序的执行效率和响应速度。在实际应用中,合理选择并发工具和优化策略,将大大提高系统的可扩展性和稳定性。 阅读详情

博客源码:here

〇、多线程和线程池

1.多线程的实现方式

(1)继承Thread类

package thread;

public class Mythread extends Thread{
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName()+" mythread...");
    }

    public static void main(String[] args) {
        Thread t1=new Mythread();
        Thread t2=new Mythread();
        Thread t3=new Mythread();
        t1.start();
        t2.start();
        t3.start();
    }
}

在这里插入图片描述

(2)实现Runnable接口

package thread;

public class MyRunnable implements Runnable{
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName()+" mythread...");
    }

    public static void main(String[] args) {
        MyRunnable r=new MyRunnable();
        new Thread(r).start();
        new Thread(r).start();
        new Thread(r).start();
    }
}

在这里插入图片描述

(3)实现Callable接口

package thread;

import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;

public class MyCallable implements Callable{
    @Override
    public String call() throws Exception {
        System.out.println(Thread.currentThread().getName()+" mythread...");
        return "success";
    }

    public static void main(String[] args) {
        MyCallable myCallable=new MyCallable();
        FutureTask<String> futureTask=new FutureTask<String>(myCallable);
        new Thread(futureTask).start();

        //获取执行结果
        try {
            String str=futureTask.get();//会调用call()的执行结果
            System.out.println("执行结果:"+str);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

在这里插入图片描述

三种实现方式的区别

  • 实现Runnable/Callable vs 继承Thread:
    优点: 线程类只是实现了Runnable接口或Callable接口,还可以继承其他类,而继承Thread的方式不能再继承其他类。在这种方式下,多个线程可以共享同一个 target对象,所以非常适合多个相同线程来处理同一份资源的情况,从而可以将CPU、代码和数据分开,形成清晰的模型,较好地体现了面向对象的思想。
    缺点: 编程稍微复杂,如果要访问当前线程,则必须使用Thread.currentThread()方法;而继承Thread的方式不仅编程简单,直接使用 this 即可获得当前线程。

  • 实现Runnable vs 实现Callable:
    Callable的任务执行后可返回值,而Runnable的任务是不能返回值的;
    Callable的方法可以抛出异常,Runnable的方法不可以;
    运行Callable任务可以拿到一个Future对象,表示异步计算的结果,通过Future对象可以了解任务执行情况,可取消任务的执行,还可获取执行结果。

2.为什么使用线程池

  • 线程池能够对线程进行统一分配,调优和监控:
    降低资源消耗(线程无限制地创建,然后使用完毕后销毁)
    提高响应速度(无须创建线程)
    提高线程的可管理性

一、线程池基本工作原理

核心实现类ThreadPoolExecutor

(1)参数

public ThreadPoolExecutor(int corePoolSize,
                          int maximumPoolSize,
                          long keepAliveTime,
                          TimeUnit unit,
                          BlockingQueue<Runnable> workQueue,
                          RejectedExecutionHandler handler)
  • int corePoolSize: 线程池中的核心线程数
  • int maximumPoolSize: 线程池中允许的最大线程数
  • long keepAliveTime: 线程空闲时的存活时间
  • TimeUnit unit: 上一个参数的时间单位
  • BlockingQueue<Runnable> workQueue: 等待队列的类型,包括了ArrayBlockingQueue(基于数组结构的有界阻塞队列)、LinkedBlockingQueue(基于链表结构的阻塞队列)、SynchronousQueue(相当于限定大小为一的等待队列)、PriorityBlockingQueue(具有优先级的无界阻塞队)。
  • ThreadFactory: 创建线程的工厂,通过自定义的线程工厂可以给每个新建的线程设置一个具有识别度的线程名。默认为DefaultThreadFactory。
  • RejectedExecutionHandler handler: 拒绝策略,包括了AbortPolicy(直接抛出异常,默认策略)、CallerRunsPolicy(用调用者所在的线程来执行任务)、DiscardOldestPolicy(丢弃阻塞队列中靠最前的任务,并执行当前任务)、DiscardPolicy(直接丢弃任务)。也可以根据应用场景实现RejectedExecutionHandler接口,自定义饱和策略,如记录日志或持久化存储不能处理的任务。

(2)继承层次

在这里插入图片描述

  • Executor接口:
    Executor 提供了一种思想:将任务提交和任务执行进行解耦。 用户只需要提交任务,提供 Runnable 对象,将任务的运行逻辑提交到执行器(Executor)中;至于任务如何执行、调度,由Executor进行处理。

  • ExecutorService接口:
    增加了一些能力: 扩展了可异步跟踪执行任务生成返回值 Future 的方法,如 submit() 等方法。提供了管控线程池生命周期的方法,如 shutDown(),shutDownNow() 等。

  • AbstractExecutorService抽象类:
    将执行任务的流程串联了起来, 保证下层的实现只需关注一个执行任务的方法即可。

  • ThreadPoolExecutor:
    实现最复杂的运行部分 ,一方面维护自身的生命周期,另一方面同时管理线程和任务,使两者良好的结合从而执行并行任务。

工作原理

在这里插入图片描述

二、线程池分类

通过调用 Executors类中的静态工厂方法可创建不同的线程池 ,这些线程池的内部实现原理都是相同的,仅仅是使用了不同的工作队列或线程池大小。

注意:实际上并不推荐通过Executors类来创建线程池,而要通过ThreadPoolExecutor方法自定义创建,原因是Executors类提供的几种线程池有不同的短板,容易引起OOM、浪费资源的问题;而且这几种线程池把参数限定了,缺少了灵活性。

newFixedThreadPool

固定大小的线程池:

public static ExecutorService newFixedThreadPool(int nThreads) {
    return new ThreadPoolExecutor(nThreads, nThreads,
                                0L, TimeUnit.MILLISECONDS,
                                new LinkedBlockingQueue<Runnable>());
}
  • 缺点:
    线程空闲了也不会被销毁,带来资源的浪费;
    由于使用了无界队列, 所以FixedThreadPool永远不会拒绝, 即饱和策略失效,有可能会出现OOM问题。

newSingleThreadExecutor

大小为1的线程池:

public static ExecutorService newSingleThreadExecutor() {
    return new FinalizableDelegatedExecutorService
        (new ThreadPoolExecutor(1, 1,
                                0L, TimeUnit.MILLISECONDS,
                                new LinkedBlockingQueue<Runnable>()));
}
  • 缺点:
    线程空闲了也不会被销毁,带来资源的浪费;
    由于使用了无界队列, 所以FixedThreadPool永远不会拒绝, 即饱和策略失效,有可能会出现OOM问题。

newCachedThreadPool

线程池的线程数可达到Integer.MAX_VALUE,线程空闲一定时间后会被销毁,使用SynchronousQueue等待队列,不会出现OOM。

public static ExecutorService newCachedThreadPool() {
    return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                    60L, TimeUnit.SECONDS,
                                    new SynchronousQueue<Runnable>());
}

三、线程池的使用

1.提交任务

(1)execute()

import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class ExecuteTest {
    public static void main(String[] args) {
        //创建一个线程池
        ThreadPoolExecutor pool=new ThreadPoolExecutor(3, 3, 60, TimeUnit.SECONDS, new LinkedBlockingQueue<>());
        pool.execute(new Task1());
        pool.execute(new Task2());
        pool.execute(new Task3());
        pool.shutdown();
    }
}

class Task1 implements Runnable{
    @Override
    public void run() {
        System.out.println("正在执行Task1");
    }
}

class Task2 implements Runnable{
    @Override
    public void run() {
        System.out.println("正在执行Task2");
    }
}

class Task3 implements Runnable{
    @Override
    public void run() {
        System.out.println("正在执行Task3");
    }
}

在这里插入图片描述

(2)submit()

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class SubmitTest {
    public static void main(String[] args) throws ExecutionException, InterruptedException{
        //创建一个线程池
        ThreadPoolExecutor pool=new ThreadPoolExecutor(3, 3, 60, TimeUnit.SECONDS, new LinkedBlockingQueue<>());
        //submit一个callable任务
        Future<String> future=pool.submit(new Task(1));
        //获取callable任务执行结果
        while(!future.isDone()){
            System.out.println("获取执行结果:"+future.get());
        }
        pool.shutdown();
    }
}

class Task implements Callable<String>{
    private int id;
    public Task(int id){
        this.id=id;
    }

    @Override
    public String call() {
        System.out.println("正在执行Task id:"+id);
        return "success";
    }
}

在这里插入图片描述

2.定时任务及周期性任务

使用TimerTask和Timer实现周期定时任务

创建一个定时任务,每隔2s执行一次。

package schedule;

import java.text.SimpleDateFormat;
import java.util.*;

public class TimerTest {
    public static final SimpleDateFormat FORMAT=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    public static void main(String[] args) {
        //创建一个TimerTask
        TimerTask timerTask=new TimerTask() {
            @Override
            public void run() {
                System.out.println("执行任务:"+FORMAT.format(new Date()));
                try{
                    Thread.sleep(3000);
                }catch(InterruptedException e){
                    e.printStackTrace();
                }
            }
        };
        //创建Timer执行周期定时任务
        System.out.println("现在是:"+FORMAT.format(new Date()));
        Timer timer=new Timer();
        //从现在开始,每间隔2s执行一次timerTask
        timer.schedule(timerTask,new Date(), 2000);
        
    }
    
}

在这里插入图片描述

  • 缺点:
    ①如果有多个TimerTask对象,Timer对象执行它们是在同一个线程里,会导致定时任务不准确。
    ②Timer线程并不捕获异常,所有TimerTask抛出的未检查的异常都会终止Timer线程。

ScheduledThreadPoolExecutor的替换Timer

使用ScheduledThreadPoolExecutor替换Timer可以解决单线程和异常导致终止的问题:

package schedule;

import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class ScheduledThreadPoolExecutorTest {
    public static final SimpleDateFormat FORMAT=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    public static void main(String[] args) {
        //创建多个TimerTask
        TimerTask timerTask1=new TimerTask() {
            @Override
            public void run() {
                System.out.println("执行任务1:"+FORMAT.format(new Date()));
                try{
                    Thread.sleep(3000);
                }catch(InterruptedException e){
                    e.printStackTrace();
                }
            }
        };
        TimerTask timerTask2=new TimerTask() {
            @Override
            public void run() {
                System.out.println("执行任务2:"+FORMAT.format(new Date()));
                try{
                    Thread.sleep(3000);
                }catch(InterruptedException e){
                    e.printStackTrace();
                }
            }
        };
        //创建ScheduledThreadPoolExecutor执行周期定时任务
        System.out.println("现在是:"+FORMAT.format(new Date()));
        ScheduledThreadPoolExecutor pool=new ScheduledThreadPoolExecutor(2);
        pool.scheduleAtFixedRate(timerTask1, 0, 1000, TimeUnit.MILLISECONDS);
        pool.scheduleAtFixedRate(timerTask2, 0, 2000, TimeUnit.MILLISECONDS);
    }
    
}

在这里插入图片描述

3.关闭线程池

(1)线程池的状态

在这里插入图片描述

(2)如何正确关闭线程池

代码粘贴自here

//调用shutdown()方法关闭线程池        
pool.shutdown();
try{
     //等待60秒
     if (!pool.awaitTermination(60, TimeUnit.SECONDS)){
         //调用shutdownNow取消正在执行的任务
         pool.shutdownNow();
         //再次等待60秒,如果还未结束,可以再次尝试,或者直接放弃
         if(!pool.awaitTermination(60, TimeUnit.SECONDS)){
             System.err.println("线程池任务未正常执行结束");
         }
     }
 }catch(InterruptedException ex){
     //重新调用shutdownNow
     pool.shutdownNow();
 }

四、 生产环境配置公式

配置线程池参数没有“银弹”,必须根据业务类型(CPU 密集型 vs IO 密集型)来定。

1. CPU 密集型 (计算型)

  • 特点: 大量计算,CPU 占用高(如加密、压缩、图像处理)。
  • 目标: 减少线程切换带来的上下文开销。
  • 公式:
    核心线程数 = CPU 核数 + 1 \text{核心线程数} = \text{CPU 核数} + 1 核心线程数=CPU 核数+1
    (+1 是为了防止某个线程发生缺页中断等暂停时,CPU 闲置)

2. IO 密集型 (业务型)

  • 特点: 大量网络请求、数据库查询、文件读写,CPU 经常在等待 IO 返回。
  • 目标: 在 IO 等待期间,让 CPU 去处理其他线程的任务。
  • 公式 A (保守):
    核心线程数 = CPU 核数 × 2 \text{核心线程数} = \text{CPU 核数} \times 2 核心线程数=CPU 核数×2
  • 公式 B (精确 - 推荐):
    核心线程数 = CPU 核数 × ( 1 + IO 耗时 CPU 耗时 ) \text{核心线程数} = \text{CPU 核数} \times (1 + \frac{\text{IO 耗时}}{\text{CPU 耗时}}) 核心线程数=CPU 核数×(1+CPU 耗时IO 耗时​)
    例如:一个任务总耗时 100ms,其中 CPU 计算 10ms,等待 DB 90ms。则线程数 = 核数 * (1 + 90/10) = 10倍核数。

生产避坑指南

  1. 禁止使用 Executors 创建线程池:
    • Executors.newFixedThreadPool 和 newSingleThreadExecutor 的队列是 LinkedBlockingQueue,长度为 Integer.MAX_VALUE,容易堆积大量请求导致 OOM。
    • Executors.newCachedThreadPool 的最大线程数是 Integer.MAX_VALUE,容易创建大量线程导致 CPU 100% 或 OOM。
  2. 动态调整:
    • 业务流量是波动的,建议引入配置中心(如 Nacos、Apollo),支持动态修改线程池参数并实时生效,无需重启服务。
  3. 监控告警:
    • 必须监控线程池的 ActiveCount(活跃线程数)、QueueSize(队列积压数)。当队列积压超过 80% 时触发告警。

掌握 ThreadPoolExecutor 不仅是背诵参数,更在于理解其核心 -> 队列 -> 救急 -> 拒绝的流量控制思想。在生产环境中,请务必手动创建线程池,结合业务属性(CPU/IO)计算参数,并做好监控与兜底策略。

深入浅出Java多线程 7.1 线程与进程的区别 进程:指在系统中正在运行的一个应用程序;程序一旦运行就是进程;进程——资源分配的最小单位。 线程:系统分配处理器时间资源的基本单元,或者说进程之内独立执行的一个单元执行流。线程——程序执行的最小单位。 也就是,进程可以包含多个线程,而线程是程序执行的最小单位。 7.2 创建线程的方法 继承Thread类 实现Runable接口 线程池方式创建 通过Cal... 阅读详情

相关推荐

【Python深入浅出㉛】Python3多线程:解锁高效并发编程

在 Python3 编程领域,多线程是一项极为关键的技术。线程作为 CPU 调度的最小单位,与进程有着本质区别,进程是资源分配的最小单位,一个进程可包含多个线程,它们共享进程资源。多线程编程赋予程序诸多显著优势,在图形用户界面应用中,能确保界面在执行其他任务时保持流畅响应,提升用户体验;在数据处理任务里,可充分利用 CPU 多核处理能力,实现任务并行执行,大幅加快程序运行速度,同时提高资源利用率。

邓邓子的博客 1331

深入理解进程与线程:并发编程实战【深入浅出】

本文介绍了进程与线程的基本概念,重点讲解了Python多线程编程的实现方法以及线程同步机制。主要内容包括:进程是资源单位,线程是执行单位;单线程与多线程的区别;并发与并行的概念;threading模块的常用函数及守护线程的使用;多线程的两种实现方式(直接导入Thread和继承Thread类);通过银行取现案例引出线程同步问题,并介绍互斥锁(RLock)的应用,最后以售票系统模拟案例展示锁的实际使用。文章通过多个代码示例帮助理解多线程编程中的核心概念和常见问题。

去码头整点薯条 3045

【SpringBoot深入浅出系列】SpringBoot之多线程

多线程编程是提升 Spring Boot 应用性能和响应速度的重要手段。通过本文的介绍,我们了解了多线程的基本概念、Spring Boot 中的多线程应用场景、实现方式以及常见问题的解决方案。在实际开发中,我们需要根据具体的业务需求和场景,合理运用多线程技术,以实现高效、稳定的应用程序。希望本文能为读者在 Spring Boot 多线程编程方面提供有益的参考和帮助,让大家能够更好地掌握和应用这一强大的技术。

邓邓子的博客 1608

深入浅出:Python 线程与并发编程

一个进程中可以包含多个线程,这些线程共享进程的资源(如内存、文件描述符等),但每个线程都有自己独立的执行路径。当多个线程同时访问共享资源时,可能会导致竞争条件(race condition),即不同的线程以不可预测的顺序修改相同的变量,从而产生不一致的结果。当线程完成对资源的访问后,它会自动释放信号量,允许其他等待的线程进入。在这个例子中,我们创建了一个事件对象,并让多个线程等待该事件的发生。通过预先创建一组线程,并将任务分配给这些线程,可以避免频繁创建和销毁线程带来的开销。锁是最基本的同步机制。

软件架构师笔记 993

足球大数据分析入门:从赔率到预测的完整流程(附数据集)

本文提供了一份足球大数据分析的完整实战指南,涵盖从数据采集、清洗、特征工程到模型构建与评估的全流程。文章详细介绍了如何利用公开数据集与API获取数据,并通过逻辑回归、随机森林等模型进行比赛结果预测,最后强调了模型评估与策略回测的重要性,帮助读者构建自己的分析框架。

r7s8t的博客 404

微信Dat文件转图片(文末含工具下载)

PC端微信dat图片转换为jpg格式

weixin_40704848的博客 8081

深入浅出线程池:解析线程池

线程池是一种多线程处理形式,它维护着一个线程集合,可以重复利用线程来执行多个任务,从而减少线程创建和销毁的开销,提高程序性能。在 Java 中,线程池(Thread Pool)是一种管理和复用线程的机制,它预先创建一定数量的线程,将任务提交到线程池后,线程池会分配空闲线程执行任务,任务完成后线程不会被销毁,而是回到线程池等待新任务,从而避免频繁创建和销毁线程的开销。线程池是并发编程的 "瑞士军刀",它通过复用线程、控制并发、缓冲任务,解决了线程频繁创建销毁的性能问题。

daidaixiaohai的博客 953

小红书图文AI创作:输入主题,一键生成图文(coze工作流教程+获取)

输入主题,工作流一键生成小红书风格图文,30s一条,可批量生成

2301_79384090的博客 2798

8w字 | Java并发编程 全套功法

优快云统计字数:77153字,Java多线程从入门到精通,由浅入深。:heart::heart:[建议收藏!]:heart::heart: 文章结合代码与理论,形象的解释了JMM模型、各种锁......

Javaer 3万+

【FPGA】安路FPGA下载器驱动安装教程

#来自学渣的问候 最近正在参加19年的FPGA创新设计大赛,然后我们选择了安路(全名:上海安路信息科技有限公司)的 FPGA 开发板。安路算是国产FPGA中还不错的一家,和紫光一样,除了自主生产的FPGA,也开始拥有了自己的编译环境。 好了。言归正传,写这篇博客的原因是,前几天在安装 安路 的编译环境和下载器驱动的时候,出了点问题,弄得心烦意乱。所以打算解决之后写篇博客,避开这个神奇的问题。 首先...

Ninquelote的博客 2万+

Cesium 实战 28 - 三维视频融合(视频投影)

Cesium 实战 27 - 三维视频融合(视频投影)。

非科班Java出身GISer的博客 3368

106、Python并发编程:深入浅出理解线程池的内部实现原理

本文围绕着ThreadPoolExecutor和Future对象的源码,深入介绍了相应的内部实现,以及线程池任务的处理全流程。对Future对象的设计理念和基础操作,也做了相应的展开介绍。这些都是理解线程池并发编程的核心,希望您能有所收获。

南宫理的日知录 708

9篇9章1节:认识 SHARE 数据库

SHARE数据库是欧洲最大的跨国老龄化追踪调查项目,覆盖28个欧洲国家和以色列的50岁及以上人群。自2004年启动以来,已完成14-16万受访者的50-60万次访谈,形成跨度20年的纵向数据。该数据库采用标准化的多阶段抽样方法,收集健康、经济和社会关系等领域的多维度信息,具有高度的跨国可比性。SHARE与美国HRS、英国ELSA等调查对接,构成全球老龄化研究网络。数据免费向科研人员开放,但需注册并承诺仅用于非商业性研究。该项目由欧盟委员会等多方资助,为老龄化研究和政策制定提供了重要实证依据。

MD Code 900

深入浅出Python多线程、多进程和并发编程

并发编程是解决现代计算机应用中性能瓶颈的重要工具,本文的目的是帮助你掌握这一强大技术,让你能够更好地应对多任务、高并发的编程需求。通过开发这两个通用函数模板,用户可以在自己的项目中轻松使用多线程和多进程,只需编写具体的任务函数并传入合适的线程数量或进程数量,即可快速实现并发处理,提高程序的性能和效率。这个并发通用函数模板允许用户同时使用多线程和多进程,根据实际情况选择合适的线程数量和进程数量,充分利用硬件资源,提高程序的性能。一个常见的方法是使用细粒度的锁,以减少锁的粒度,只保护必要的资源。

u013112984的博客 1406

CKA-CN考试之路----2

部分知道就可以了,考试不用输入,后面不再复述.这里我们需要将两端内容凭借成1个yaml。执行题目中给的的命令进行测试。

Q先生 242

Codex 实战 Skills:编写 Skill 自动为 ESP32 芯片生成 MQTT 订阅与发布的基础代码

为了更清晰地展示 Skill 的工作原理和两种语言的差异,以下提供原理图和比对表格。本文深入探讨了如何利用 Codex 的 Agent 智能体技能(Skills)自动化 ESP32 与 MQTT 通信的代码生成过程。我们首先分析了 IoT 开发的痛点,然后详细设计了 Skill 的输入配置,并分别提供了 MicroPython 和 C++ 两种语言的完整代码实现。通过对比两种语言的优缺点,帮助开发者根据项目需求选择合适的语言。最后,我们提供了详细的运行指南,确保开发者能够快速上手。Skill 设计哲学。

yueyeguzhuo的专栏 82

Java高并发编程之第一阶段,多线程基础深入浅出

汪文君高并发编程第一阶段01讲-课程大纲及主要内容介绍 汪文君高并发编程第一阶段02讲-简单介绍什么是线程 汪文君高并发编程第一阶段03讲-创建并启动线程 汪文君高并发编程第一阶段04讲-线程生命周期以及start方法源码剖析 汪文君高并发编程第一阶段05讲-采用多线程方式模拟银行排队叫号 汪文君高并发编程第一阶段06讲-用Runnable接口将线程的逻辑执行单元从控制中抽取出来 汪文君高并发编程第一阶段07讲-策略模式在Thread和Runnable中的应用分析 汪文君高并发编程第一阶段08讲-构造Thr

清心寡欲,做一个专注的程序员 1万+

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

深入浅出Java并发编程:理解与应用线程池

深入理解和掌握Java线程池是每个Java开发者进阶高级阶段的重要步骤。它不仅能帮助我们编写出高效、稳定的并发程序,更能让我们在设计和优化系统架构时拥有更多的可能性和灵活性。希望这篇文章能为大家打开Java并发世界的一扇窗,激发你对线程池更深层次的研究和探索💪!

aLearnerForJAVA的博客 757

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

深入浅出Java多线程从基础概念到并发编程实战

Java多线程编程是一个广阔而深奥的领域。从理解基本的线程概念和创建方式,到掌握同步机制保证线程安全,再到熟练运用JUC工具包解决复杂的并发问题,每一步都需要理论与实践相结合。在实际开发中,除了技术实现,更要关注线程池的参数调优、避免死锁、性能监控等问题。随着硬件的发展,异步编程(如CompletableFuture)、响应式编程(如Project Reactor)等新的并发范式也日益重要。持续学习和实践是驾驭Java并发编程这匹“烈马”的不二法门。

currypop17的博客 496

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

深入浅出Java多线程从基础概念到高级并发编程实战

Java并发包(java.util.concurrent)提供了线程安全的集合类,如ConcurrentHashMap、CopyOnWriteArrayList,它们通过分段锁或写时复制技术实现高效并发。原子类(如AtomicInteger)使用CAS(Compare-And-Swap)操作保证单个变量的原子性,无需加锁,性能更高。此外,Java.util.concurrent.locks包提供了更灵活的Lock接口,如ReentrantLock,它支持公平锁、条件变量等高级特性。

u011779969的博客 271

Java中的多线程和并发编程

大家好,我是城南。在当今这个信息爆炸的时代,了解和掌握多线程和并发编程技术已经成为Java开发者的必备技能。无论你是新手小白,还是经验丰富的开发者,本文将带你深入浅出地探讨Java中的多线程和并发编程,让你轻松驾驭这一复杂但又至关重要的领域。

weixin_46372265的博客 1013

多线程四大经典案例

目录 1.单线模式 1.1饿汉模式 1.2懒汉模式 2.阻塞式队列 2.1阻塞队列是什么 2.2生产者消费者模型 2.3标准库中的阻塞队列 2.4阻塞队列的实现 3.定时器 3.1定时器是什么 3.2标准库中的定时器 3.3实现定时器 4.线程池 4.1什么是线程池 4.2标准库中的线程池 4.3实现线程池 1.单线模式 ①什么是单例模式: 单例模式是校招中最常考的设计模式之一. ②什么是设计模式: 设计模式好比象棋中的 "棋谱". 红方当头炮,..

weixin_58850105的博客 8139

视频教程-多线程与线程池技术详解-Java

多线程与线程池技术详解 系统分析师,项目经理,特级讲师;11年项目经验,8年...

weixin_32193293的博客 565

站在巨人的肩膀上学习:五位阿里大牛联手撰写的《深入浅出Java多线程》

写在前面 多线程相对于其他 Java 知识点来讲,有一定的学习门槛,并且了解起来比较费劲。在平时工作中如若使用不当会出现数据错乱、执行效率低(还不如单线程去运行)或者死锁程序挂掉等等问题,所以掌握了解多线程至关重要。 笔者在读完市面上关于Java并发编程的资料后,感觉有些知识点不是很清晰,于是在RedSpider社区内展开了对Java并发编程原理的讨论。鉴于开源精神,我们决定将我们讨论之后的Java并发编程原理整理成书籍,分享给大家。 站在巨人的肩上,我们可以看得更远。本书内容的主要来源有博客、书籍、

Java技术开发工程师的博客 397

深入浅出java线程池

线程池的概念 线程池(Thread Pool)是一种基于池化思想管理线程的工具,经常出现在多线程服务器中,如MySQL,ElasticSearch等等 线程池解决的核心问题就是资源管理问题。在并发环境下,系统不能够确定在任意时刻中,有多少任务需要执行,有多少资源需要投入。这种不确定性将带来以下若干问题: 频繁申请/销毁资源和调度资源,将带来额外的消耗,可能会非常巨大。 对资源无限申请缺少抑制手段,易引发系统资源耗尽的风险。 系统无法合理管理内部的资源分布,会降低系统的稳定性。 为解决资源分配这个问题,线

leon 6181

阿里P8专家耗时半年整理的“深入浅出多线程与高并发”看完你不涨薪谁涨薪?

在读完市⾯上关于Java并发编程的资料后,感觉有些知识点不是很清晰,于是展开了对Java并发编程原理的讨论。鉴于开源精神,决定将我们讨论之后的Java并发编程原理整理成电子书籍,分享给⼤家。 站在巨⼈的肩上,我们可以看得更远。本文档内容的主要来源有博客、书籍、论⽂,对于⼀些已经叙述得很清晰的知识点我们直接引⽤在本书中;对于⼀些没有讲解清楚的知识点,我们加以画图或者编写Demo进⾏加⼯;⽽对于⼀些模棱两可的知识点,本文档在查阅了⼤量资料的情况下,给出最合理的解释。 这边文档的过程也是对⾃⼰研究和掌握的技术

bieber007的博客 189
上一篇: 并发编程(三):深度解析Volatile 与 Java 内存模型 (JMM)
下一篇: 并发编程(五):ThreadLocal原理、内存泄漏与最佳实践
TracyCoder123
博客等级 码龄8年 1万+粉丝 226原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

TracyCoder123

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值