Java 并发编程框架(二)

Java 并发编程面试二 synchronized 是和 if、else、for、while 一样的关键字,ReentrantLock 是类,1、Callable 规定(重写)的方法是 call(),Runnable 规定(重写)的方法是 run()。2、Thread1 的构造方法、静态块是 Thread2 调用的,Thread1 的 run()方法是。1、Thread2 的构造方法、静态块是 main 线程调用的,Thread2 的 run()方法是。所以 CyclicBarrier 能处理更为复杂的业务场景,比如如果。 阅读详情

Java 并发编程框架(二)

在基本了解了并发线程的主要类以后(如果你对这些类没有基本的概念,请阅读Java 并发编程框架(一))
这篇文章会对前一篇文章提及的主要类做进一步说明

CompletionService

CompletionService究竟是什么,如果一开始很难理解它,那么我们可以通过一个Demo来模仿一下ExecutorCompletionService这个实现类

Case.Java 测试用例

public class Case
{
    public static void main(String[] args)
    {

        CommonCompletionService commonCompletionService = new CommonCompletionService();

        commonCompletionService.submit(CompletionCase.COMPLETION_MANUL);
    }

    public static enum FutureCase
    {
        FUTURETASK_EXECUTOR, FUTURE_EXECUTOR, FUTURETASK_THREAD, COMPLETIONSERVICE
    }

    public static enum CompletionCase
    {
        COMPLETION_MANUL, COMPLETION_LIB
    }

}

CommonCompletionService.java 业务逻辑类

import java.util.Random;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Callable;
import java.util.concurrent.CompletionService;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorCompletionService;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.LinkedBlockingQueue;

import com.executor.demo.Case.CompletionCase;


public class CommonCompletionService
{
    public static class WorkBack implements Callable<String>
    {
        private String name;

        public WorkBack(String name)
        {
            this.name = name;
        }

        @Override
        public String call() throws Exception
        {
            try
            {
                Thread.sleep(new Random().nextInt(2000));
            }
            catch (Exception e)
            {
                e.printStackTrace();
            }

            return name;
        }
    }

    private static final int TASK_TOTAL = 10;

    public void submit(CompletionCase completionCase)
    {
        if (completionCase == null) return;

        switch (completionCase)
        {
        case COMPLETION_MANUL:

            ExecutorService pool = Executors.newFixedThreadPool(5);
            BlockingQueue<Future<String>> queue = new LinkedBlockingQueue<Future<String>>();

            for (int i = 0; i < TASK_TOTAL; i++)
            {
                Future<String> future = pool.submit(new WorkBack(Thread.currentThread().getName() + " " + i));

                queue.add(future);
            }

            for (int i = 0; i < TASK_TOTAL; i++)
            {
                try
                {
                    System.out.println("COMPLETION_MANUL:" + queue.take().get());
                }
                catch (InterruptedException e)
                {
                    e.printStackTrace();
                }
                catch (ExecutionException e)
                {
                    e.printStackTrace();
                }
            }

            pool.shutdown();

            break;

        case COMPLETION_LIB:

            ExecutorService pool2 = Executors.newFixedThreadPool(5);
            CompletionService<String> completionService = new ExecutorCompletionService<String>(pool2);

            for (int i = 0; i < TASK_TOTAL; i++)
            {
                completionService.submit(new WorkBack(Thread.currentThread().getName() + " " + i));
            }

            for (int i = 0; i < TASK_TOTAL; i++)
            {
                try
                {
                    System.out.println("COMPLETION_LIB:" + completionService.take().get());
                }
                catch (InterruptedException e)
                {
                    e.printStackTrace();
                }
                catch (ExecutionException e)
                {
                    e.printStackTrace();
                }
            }

            pool2.shutdown();

            break;

        default:
            break;
        }

    }
}

运行结果:

COMPLETION_MANUL:main 0
COMPLETION_MANUL:main 1
COMPLETION_MANUL:main 2
COMPLETION_MANUL:main 3
COMPLETION_MANUL:main 4
COMPLETION_MANUL:main 5
COMPLETION_MANUL:main 6
COMPLETION_MANUL:main 7
COMPLETION_MANUL:main 8
COMPLETION_MANUL:main 9

接下来分析一下上面的程序,case COMPLETION_MANUL:这个部分的程序是模仿CompletionService的简单实现,而case COMPLETION_LIB:这个部分程序就是CompletionService简单Demo,所以对比上下这个两部分程序,可以看出,CompletionService的主要功能是封装了具有BlockingQueue的ExecutorService线程池,这样理解起来比较形象,其实看看CompletionServic的实现类,也是这样做的,感兴趣的话可以看看源代码,以便更深入的理解。

ThreadPoolExecutor

还记得Java 并发编程框架(一)这篇文章中提及的Executors 其中比较重要的静态方法,仔细看看代码会发现,这些静态方法都指向了同一个类ThreadPoolExecutor,很明显它是线程池的生成类,接下来如果想进一步了解线程池,那么不可避免的会和这个类打交道了。

public class ThreadPoolExecutor extends AbstractExecutorService {
    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;
    }
    ...
}

我们重点看一下参数是5个的构造器即可,下面解释一下这5个参数分别代表神马意思。

  • corePoolSize:线程池中所保存的核心线程数,包括空闲线程。
  • maximumPoolSize:线程池中允许的最大线程数。
  • keepAliveTime:线程池中的空闲线程所能持续的最长时间。
  • unit:持续时间的单位。
  • workQueue:任务执行前保存任务的队列,仅保存由execute方法提交的Runnable任务。

这些个参数一开始很容易让人望文生义:线程池里保持corePoolSize个线程,如果不够用,就加线程入池直至maximumPoolSize大小,如果还不够就往workQueue里加,如果workQueue也不够就用RejectedExecutionHandler来做拒绝处理。

在你认真查看ThreadPoolExecutor源代码上面一大段英文注释过后,你会发现上面的理解是多么可笑,下面将原文翻译过后大概的理解说一下:(为了表述上的方便我们定义一下当前线程池线程数量为CurrentPoolSize)

  • When CurrentPoolSize < corePoolSize,即使线程池部分线程闲的蛋疼的,只要有新添加的任务,那么就会创建新的线程去完成这个任务。
  • When CurrentPoolSize >= corePoolSize && workQueue 未满新添加的任务放到workQueue中,按照FIFO的原则依次等待执行
  • When CurrentPoolSize >= corePoolSize && workQueue 已满 这个时候就会增加新的线程,只要此时CurrentPoolSize < maximumPoolSize,那么corePoolSize < CurrentPoolSize < maximumPoolSize 这部分线程如果闲的蛋疼怎么办?这个时候轮到keepAliveTime审判官登场了,如果超过这个时间,这些闲的蛋疼的线程死期就到了。
  • When CurrentPoolSize == maximumPoolSize就用RejectedExecutionHandler来做拒绝处理

上面解释了基本的参数含义,接下来看看上文提及的Executor静态方法

newFixedThreadPool

public class Executors {
    public static ExecutorService newFixedThreadPool(int nThreads) {
            return new ThreadPoolExecutor(nThreads, nThreads,
                                          0L, TimeUnit.MILLISECONDS,
                                          new LinkedBlockingQueue<Runnable>());
        }
}

它将corePoolSize和maximumPoolSize都设定为了nThreads,这样便实现了线程池的大小的固定,不会动态地扩大,另外,keepAliveTime设定为了0,也就是说线程只要空闲下来,就会被移除线程池,关于LinkedBlockingQueue后面会给出详细说明。

newCachedThreadPool

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

它将corePoolSize设定为0,而将maximumPoolSize设定为了Integer的最大值,线程空闲超过60秒,将会从线程池中移除。由于核心线程数为0,因此每次添加任务,都会先从线程池中找空闲线程,如果没有就会创建一个线程(SynchronousQueue决定的,后面会说)来执行新的任务,并将该线程加入到线程池中,而最大允许的线程数为Integer的最大值,因此这个线程池理论上可以不断扩大。

Queue排队策略

  • 直接提交。直接提交策略表示线程池不对任务进行缓存。新进任务直接提交给线程池,当线程池中没有空闲线程时,创建一个新的线程处理此任务。这种策略需要线程池具有无限增长的可能性。实现为:SynchronousQueue
  • 有界队列。当线程池中线程达到corePoolSize时,新进任务被放在队列里排队等待处理。有界队列(如ArrayBlockingQueue)有助于防止资源耗尽,但是可能较难调整和控制。队列大小和最大池大小可能需要相互折衷:使用大型队列和小型池可以最大限度地降低 CPU 使用率、操作系统资源和上下文切换开销,但是可能导致人工降低吞吐量。如果任务频繁阻塞(例如,如果它们是 I/O 边界),则系统可能为超过您许可的更多线程安排时间。使用小型队列通常要求较大的池大小,CPU 使用率较高,但是可能遇到不可接受的调度开销,这样也会降低吞吐量。
  • 无界队列。使用无界队列(例如,不具有预定义容量的 LinkedBlockingQueue)将导致在所有 corePoolSize 线程都忙时新任务在队列中等待。这样,创建的线程就不会超过 corePoolSize。(因此,maximumPoolSize 的值也就无效了。)当每个任务完全独立于其他任务,即任务执行互不影响时,适合于使用无界队列;例如,在 Web 页服务器中。这种排队可用于处理瞬态突发请求,当命令以超过队列所能处理的平均数连续到达时,此策略允许无界线程具有增长的可能性。

RejectedExecutionHandler拒绝策略

当任务源源不断的过来,而我们的系统又处理不过来的时候,我们要采取的策略是拒绝服务。RejectedExecutionHandler接口提供了拒绝任务处理的自定义方法的机会。在ThreadPoolExecutor中已经包含四种处理策略。

  1. CallerRunsPolicy
  2. AbortPolicy
  3. DiscardPolicy
  4. DiscardOldestPolicy

分别对这个四种策略说明如下:

CallerRunsPolicy

线程调用运行该任务的 execute 本身。此策略提供简单的反馈控制机制,能够减缓新任务的提交速度。

public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
     if (!e.isShutdown()) {
         r.run();
    }
}

这个策略显然不想放弃执行任务。但是由于池中已经没有任何资源了,那么就直接使用调用该execute的线程本身来执行。(开始我总不想丢弃任务的执行,但是对某些应用场景来讲,很有可能造成当前线程也被阻塞。如果所有线程都是不能执行的,很可能导致程序没法继续跑了。需要视业务情景而定吧。)

AbortPolicy

处理程序遭到拒绝将抛出运行时 RejectedExecutionException。

public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
      throw new RejectedExecutionException();
}

这个策略直接抛出异常,丢弃任务。(jdk默认策略,队列满并线程满时直接拒绝添加新任务,并抛出异常,所以说有时候放弃也是一种勇气,为了保证后续任务的正常进行,丢弃一些也是可以接收的,记得做好记录)

DiscardPolicy

不能执行的任务将被删除。

public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {}

这种策略和AbortPolicy几乎一样,也是丢弃任务,只不过他不抛出异常。

DiscardOldestPolicy

如果执行程序尚未关闭,则位于工作队列头部的任务将被删除,然后重试执行程序(如果再次失败,则重复此过程)

public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
    if (!e.isShutdown()) {
        e.getQueue().poll();
        e.execute(r);
    }
}

该策略就稍微复杂一些,在pool没有关闭的前提下首先丢掉缓存在队列中的最早的任务,然后重新尝试运行该任务。这个策略需要适当小心。

WinInet 编程:MFC 中的互联网编程 WinInet 是一套 Windows API(应用程序编程接口),用于实现互联网应用程序的网络通信和数据传输。WinInet 抽象了底层网络协议和硬件细节,为程序员提供了一套统一的接口,简化了互联网应用程序的开发过程。WinInet 广泛应用于各种 Windows 应用程序中,包括网页浏览器、下载管理器、网络游戏等。MFC WinInet 是一套强大的类库,为 MFC 程序员提供了在 Windows 平台上实现互联网通信和数据传输的工具。 阅读详情

相关推荐

从无序到结构化:HAC框架如何用哈希网格重构3D高斯压缩范式 | ECCV2024技术解读

本文深入解读了ECCV 2024提出的HAC框架,它通过引入二值哈希网格为无序的3D高斯锚点建立空间结构,并利用上下文模型进行自适应量化,从而实现了对3D Gaussian Splatting模型的高效压缩。该方法将压缩范式从单纯削减数据转向智能理解数据关系,在保持高质量渲染的同时,显著提升了压缩率,为移动端部署和实时应用提供了新方案。

yolo5detector的博客 459

java并发编程【二】Executor框架与线程池

线程池是池化技术的一种实现,在并发编程中起到了至关重要的的作用

weixin_44050211的博客 1952

nbiot和2g_浅谈NBIOT

一、什么是NBIOT?1、概念窄带物联网(Narrow Band Internet of Things, NB-IoT),NB-IoT构建于蜂窝网络,只消耗大约180KHz的带宽,使用License频段,可采取带内、保护带或独立载波等三种部署方式,与现有网络共存。可直接部署于GSM网络、UMTS网络或LTE网络,以降低部署成本、实现平滑升级。2、NBIOT的特点和目标(1)超强覆盖:相对GPRS来...

weixin_39534100的博客 1704

Java并发编程核心方法与框架-Fork-Join分治编程(二)

待续 

umgsai的专栏 322

什么是 WhatsApp云控 WhatsApp群发,WhatsApp协议,他们有什么区别?

下面我们sensws讲解下什么是WhatsApp云控 WhatsApp群发,WhatsApp协议

sendws的博客 3875

【低照度图像增强系列】使用MSRCR(Multi-Scale Retinex with Color Restoration)算法对低照度图像进行增强处理

【低照度图像增强系列】使用MSRCR(Multi-Scale Retinex with Color Restoration)算法对低照度图像进行增强处理

静谧、淡雅 649

并发编程中级二:Java 锁框架[ReentrantLock,Condition]

2019独角兽企业重金招聘Python工程师标准>>> ...

weixin_34127717的博客 108

STM32CubeIDE开发环境搭建与GPIO控制实战

嵌入式开发中,MCU开发环境构建是软硬件协同的起点,其核心在于工具链选型、外设抽象层级与调试可靠性。HAL库作为ST官方标准硬件抽象层,通过统一接口屏蔽芯片差异,显著提升工程可移植性;而STM32CubeIDE则以图形化配置+自动生成代码的方式,实现‘配置即代码’的确定性开发范式。该组合在教学验证、原型迭代和中小规模量产中具备高性价比技术价值,广泛应用于智能传感、工业HMI及IoT终端等场景。本文聚焦STM32CubeIDE 1.15.0环境部署、MyST账户与固件包管理、ST-LINK驱动校验,以及基于H

weixin_33531560的博客 81

JAVA并发编程笔记(二)---Executor框架

一:简介 public interface Executor { void execute(Runnable command); } Executor是一个灵活而且强大的框架的基础,可以用于异步任务执行,而且支持很多不同类型的任务执行策略。它还为任务提交和任务执行之间的解耦提供了标准方法。为使用Runnable描述任务提供了通用的方式。Executor的实现提供了对生命周期的支持以及...

java1_boy的博客 325

Swin Transformer注意力计算复杂度为何比全局注意力少那么多?

本文对比分析了Vision Transformer(ViT)和Swin Transformer的计算复杂度。ViT采用全局注意力机制,计算复杂度为4[hwc^2]+2[(hw)^2C],当图像尺寸较大时计算量显著增加。而Swin Transformer采用窗口注意力机制,将图像划分为M×M的窗口(如7×7),计算复杂度降为4[hwc^2]+2[(hw)(M*M)*C]。以224×224图像为例,Swin Transformer的计算量比ViT减少约900倍,大幅节省了计算资源。文章通过矩阵乘法运算详细推导了

人工智能研究所的博客 62

AI原生SaaS应用的自动化运维体系构建

随着ChatGPT掀起的AI原生应用浪潮,越来越多SaaS(软件即服务)产品开始以"AI优先"的方式设计——从用户交互到核心功能,都深度依赖机器学习模型(如推荐算法、智能客服)、实时数据流(如用户行为分析)和弹性算力(如大模型推理)。这类应用的运维需求与传统SaaS完全不同:传统运维像"修水管",哪里漏了补哪里;AI原生运维则像"照顾会成长的宠物",需要实时感知模型状态、数据变化和流量波动,主动调整资源。

AI天才研究院 1080

探索Java高级特性的宝典:《Core Java 第12版卷二》资源推荐

探索Java高级特性的宝典:《Core Java 第12版卷二》资源推荐 【下载地址】CoreJava第12版卷二高级特性资源下载 Core Java 第12版卷二:高级特性资源下载 项目地址: https://gitcode.c...

gitblog_06685的博客 951

深度强化Q学习-基于微软AirSim仿真环境的自动驾驶案例(原理代码详解简易可行)

最近在学习《强化学习原理与Python实现》,肖智清著。参考第十二章的自动驾驶案例,写一篇总结,尽量做到简单可行,让有志于自动驾驶的小伙伴可以通过此篇博客可以管中窥豹,初步了解自动驾驶的强化学习训练过程。 本篇将自动驾驶问题转化为回合制的强化学习任务,设计以车辆观察图像和运行状态为输入的自动驾驶算法,并在AirSim仿真环境中进行训练和测试。本篇使用带经验回放和目标网络的基于深度Q网络算法设计并实现智能体,对经验回放、目标网络和深度Q学习算法进行简单介绍,并用代码实现。

shao918516的博客 8599

Java并发编程框架之Executor 框架

Java 并发编程框架是用于简化并发程序开发的一系列工具和库,它们提供了高层次的抽象来管理线程、同步机制和其他与并发相关的资源。随着Java语言的发展,这些框架不断进化,为开发者提供更加高效且易于使用的API。

物联网工程专业 - 软硬兼修 980

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

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

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

Java并发编程新纪元:探索Executor线程池框架

在Java并发编程领域,线程的创建与管理至关重要。传统通过new Thread()的方式在性能优化、资源高效利用及系统扩展性方面存在明显局限。鉴于此,本文将介绍Executor线程池框架,这一相较于传统线程创建方式更为优越的并发编程工具。Executor线程池框架通过复用线程、智能管理资源及灵活配置,显著提升了系统性能、优化了资源利用率,并增强了系统的可扩展性。

Rye的博客 2649

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

Java 并发编程之AQS

AbstractQueuedSynchronizer (AQS) 是 Java 并发编程中的一个核心框架,广泛用于构建锁和其他同步器(如信号量、读写锁等)。它是 java.util.concurrent.locks 包的一部分。AQS 的设计目的是简化并发同步器的实现。理解 AQS 对于深入理解 Java 并发编程非常重要。

微笑听雨 6763

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

java 并发编程框架

java 并发编程线程组管理Executor 框架Fork-Join框架 线程组管理 线程组: 线程的集合 大线程可包含小线程、 可管理多个线程,但效率较低 重复的创建线程和关闭线程 可通过enumerate显示所有线程 例: 使用线程组创建10个线程,每创建一个线程,休息1秒。 输出活跃的线程,所有线程列表。当活跃的线程数少于8个时,终止所有的线程。 其中,Reacher类为实现Runnable接口的类,Result类为一个存储数据的类。 package ThreadGroup; import ja

calabash_man的博客 234

java并发编程

什么是java并发编程如何进行并发编程

m0_64021225的博客 1724

java并发编程简介

最近看完《Java并发编程的艺术》一书,收获颇丰,在此写一下java并发编程的概要之类的文章,概述java并发编程的一些工具和原理。 《Java并发编程的艺术》和《java编程思想》大概内容差不多,《Java并发编程的艺术》多了些并发编程工具的原理介绍,介绍的比较深入。它里面讲的关于多核心的cpu如何进行多线程操作,线程之间的共享变量的可见性如何实现。顺序优化方面,介绍了java的编译器顺序优化、指令级优化、内存系统重排序,而为了结果的一致性,java编译器会进行插入内存屏障来限制java语句的顺序重排。然

qq_22744093的博客 3098

Java 并发编程的艺术

内容简介 书中采用循序渐进的讲解方式,从并发编程的底层实现机制入手,逐步介绍了在设计 Java 并发程序时各种重要的技术、设计模式与应用,同时辅以丰富的示例代码,使得开发人员能够更快地领悟 Java 并发编程的要领,围绕着 Java 平台的基础并发功能快速地构建大规模的并发应用程序。 第1章介绍 Java 并发编程的挑战,会向读者说明可能会遇到哪些问题,以及如何解决。 第2章 Java 并发编程...

GitChat 2693

Java并发编程实践

并发编程是指通过设计和实现多线程程序来利用计算机资源和提高程序执行效率的编程方法。它的主要特点是多线程之间的竞争和协作关系。线程安全性是指并发编程中,在多个线程访问共享数据时,对数据的访问不会产生意料之外的后果。实现线程安全性需要从数据的状态变化过程进行分析,并采用相应的线程安全策略。

BXA 2999

Java并发编程 - 第六章 Java并发容器和框架

前言: Java程序员进行并发编程时,相比于其他语言的程序员而言要倍感幸福,因为并发编程大师 Doug Lea 不遗余力地为 Java 开发者提供了非常多的并发容器和框架。本章让我们一起来见识一下大师操刀编写的并发容器和框架,并通过每节的原理分析一起来学习如何设计出精妙的并发程序。 一、ConcurrentHashMap 的实现原理与使用 1.1 为什么要使用 ConcurrentHashMap 在并发编程中使用 HashMap 可能导致程序死循环。而使用线程安全的 HashTable 效率又非常低下,基于

SongYu的博客 1万+

Java并发编程

是一个运行中的程序的实例,拥有独立的内存空间。在Java中,当运行一个Java应用程序时,例如通过命令行使用java命令,操作系统为该应用程序启动了一个新的进程。并发编程的出现主要是为了更有效地利用计算资源,特别是在多核处理器普遍存在的当代,通过并发执行可以显著提高程序的性能和响应速度。这两个例子中的进程都拥有自己的独立内存空间,可以加载不同的类和资源,它们在操作系统层面是完全独立的。当运行这个类时,Java虚拟机(JVM)会启动,操作系统会为其创建一个新的进程,然后在这个进程中执行。

ny_forever的博客 934

Akka框架——第一节:并发编程简介

本节主要内容: 1. 重要概念 2. Actor模型 3. Akka架构简介多核处理器的出现使并发编程(Concurrent Programming)成为开发人员必备的一项技能,许多现代编程语言都致力于解决并发编程问题。并发编程虽然能够提高程序的性能,但传统并发编程的共享内存通信机制对开发人员的编程技能要求很高,需要开发人员通过自身的专业编程技能去避免死锁、互斥等待及竞争条件(Race Con

摇摆少年梦的技术博客 2万+

《java并发编程的艺术》阅读笔记总结

第1章 并发编程的挑战 并发编程的目的是为了让程序运行得更快,但是不是更多的线程就能让程序最大限度的并发执行。比如上下文切换、死锁的问题,以及受限于软件和硬件的资源限制问题。 软件资源限制:有数据库的链接数和socket连接数等 硬件的资源限制有带宽的上传、下载速度、硬盘读写速度和CPU处理速度。 减少上下文切换的方法 无锁并发编程 CAS算法 使用最少线程 使用协程 避免死锁 避免...

weixin_36152448的博客 3982

【Java 并发编程】详解

在并发编程中,使用普通的集合类(如 ArrayList、HashMap 等)往往会出现线程安全问题,因为它们在设计时并没有考虑多线程并发访问的情况。Java 提供了一系列并发容器来解决这个问题,这些并发容器在保证高效性能的同时,能够支持多线程安全地进行读写等操作。

架构师之路 1123
上一篇: Java 序列化
下一篇: Java 排序算法
linroidh
博客等级 码龄16年 15粉丝 35原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值