Java 进阶多线程(二)

Java进阶 ——— Java多线程(二)之如何开启多线程 上面罗列了三种启动多线程的方式,包括继承Thread类,实现Runnable接口,使用ThreadFactory线程创建,推荐使用第二种,毕竟组合优于继承。 阅读详情

文章目录

一、线程通信(了解)

  • 概念

线程通信就是线程间相互发送数据,线程间共享一个资源即可实现线程通信

  • 常见方式

通过共享一个数据的方式实现

根据共享数据的情况决定自己该怎么做,以及通知其他线程怎么做

  • 场景

生产者与消费者模型:生产者线程负责生产数据,消费者线程负责消费生产者产生的数据

  • 要求

生产者线程生产完数据后唤醒消费者,然后等待自己,消费者消费完该数据后唤醒生产者,然后等待自己

方法名解释
void wait​()当前线程等待,直到另一个线程调用notify() 或 notifyAll()唤醒自己
void notify()唤醒正在等待对象监视器(锁对象)的单个线程
void notifyAll()唤醒正在等待对象监视器(锁对象)的所有线程

二、线程池(重点)

  • 概述

可以复用线程的技术

1、获得线程池对象

用ExecutorService实现类ThreadPoolExecutor自创建一个线程池对象

用Executors(线程池的工具类)调用方法返回不同特点的线程池对象

public ThreadPoolExecutor(
            int corePoolSize,//核心线程数
            int maximumPoolSize,//最大线程数
            long keepAliveTime,//线程空闲时间
            TimeUnit unit,//时间单位
            BlockingQueue<Runnable> workQueue,//任务队列
            ThreadFactory threadFactory,//线程工厂
            RejectedExecutionHandler handler//拒绝策略
    )
参数名解释
corePoolSize指定线程池的线程数量(核心线程),不能小于0
maximumPoolSize指定线程池可支持的最大线程数,最大数量 >= 核心线程数量
keepAliveTime指定临时线程的最大存活时间 ,不能小于0
unit指定存活时间的单位(秒、分、时、天)
workQueue指定任务队列 ,不能为null
threadFactory指定用哪个线程工厂创建线程,不能为null
handler指定线程忙,任务满的时候,新任务来了怎么办,不能为null
TimeUnit.DAYS;               //天
TimeUnit.HOURS;             //小时
TimeUnit.MINUTES;           //分钟
TimeUnit.SECONDS;           //秒
TimeUnit.MILLISECONDS;      //毫秒
TimeUnit.MICROSECONDS;      //微妙
TimeUnit.NANOSECONDS;       //纳秒

 

2、线程池处理Runnable

ExecutorService方法解释
void execute(Runnable command)执行任务/命令,没有返回值,一般用来执行 Runnable 任务
Future<T> submit(Callable<T> task)执行任务,返回未来任务对象获取线程结果,一般拿来执行 Callable 任务
void shutdown()等任务执行完毕后关闭线程池
List<Runnable> shutdownNow()立刻关闭,停止正在执行的任务,并返回队列中未执行的任务
4种策略解释
ThreadPoolExecutor.AbortPolicy丢弃任务并抛出RejectedExecutionException异常。是默认的策略
ThreadPoolExecutor.DiscardPolicy丢弃任务,但是不抛出异常 这是不推荐的做法
ThreadPoolExecutor.DiscardOldestPolicy抛弃队列中等待最久的任务 然后把当前任务加入队列中
ThreadPoolExecutor.CallerRunsPolicy由主线程负责调用任务的run()方法从而绕过线程池直接执行

1)AbortPolicy实战

当运行任务数超过核心数时,会报RejectedExecutionException错误

import java.util.concurrent.*;

public class ThreadPoolExecutorTest implements Runnable {
 
    private String name;

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

    @Override
    public void run() {
 
        try {
 
            System.out.println("当前线程名: " + Thread.currentThread().getName() + ", 任务 " + name + " is running!");
            Thread.sleep(200);
        } catch (InterruptedException e) {
 
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
 
        //线程池
        ExecutorService pools = new ThreadPoolExecutor(
                1,
                1,
                1,
                TimeUnit.SECONDS,
                new ArrayBlockingQueue<>(1),
                Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.AbortPolicy());

        ThreadPoolExecutorTest run = null;
        // 循环创建线程
        for (int i = 0; i < 5; i++) {
 
            run = new ThreadPoolExecutorTest("" + i);
            // 将任务添加到线程池中
            pools.execute(run);
        }

        //关闭线程池
        pools.shutdown();
    }
}

 

 

2)DiscardPolicy实战

import java.util.concurrent.*;

public class ThreadPoolExecutorTest implements Runnable {
 
    private String name;

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

    @Override
    public void run() {
 
        try {
 
            System.out.println("当前线程名: " + Thread.currentThread().getName() + ", 任务 " + name + " is running!");
            Thread.sleep(200);
        } catch (InterruptedException e) {
 
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
 
        //线程池
        ExecutorService pools = new ThreadPoolExecutor(
                1,
                1,
                1,
                TimeUnit.SECONDS,
                new ArrayBlockingQueue<>(1),
                Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.DiscardPolicy());

        ThreadPoolExecutorTest run = null;
        // 循环创建线程
        for (int i = 0; i < 5; i++) {
 
            run = new ThreadPoolExecutorTest("" + i);
            // 将任务添加到线程池中
            pools.execute(run);
        }

        //关闭线程池
        pools.shutdown();
    }
}

 

3)DiscardOldestPolicy实战

import java.util.concurrent.*;

public class ThreadPoolExecutorTest implements Runnable {
 
    private String name;

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

    @Override
    public void run() {
 
        try {
 
            System.out.println("当前线程名: " + Thread.currentThread().getName() + ", 任务 " + name + " is running!");
            Thread.sleep(200);
        } catch (InterruptedException e) {
 
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
 
        //线程池
        ExecutorService pools = new ThreadPoolExecutor(
                1,
                1,
                1,
                TimeUnit.SECONDS,
                new ArrayBlockingQueue<>(1),
                Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.DiscardOldestPolicy());

        ThreadPoolExecutorTest run = null;
        // 循环创建线程
        for (int i = 0; i < 5; i++) {
 
            run = new ThreadPoolExecutorTest("" + i);
            // 将任务添加到线程池中
            pools.execute(run);
        }

        //关闭线程池
        pools.shutdown();
    }
}

 

4)CallerRunsPolicy实战

import java.util.concurrent.*;

public class ThreadPoolExecutorTest implements Runnable {
 
    private String name;

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

    @Override
    public void run() {
 
        try {
 
            System.out.println("当前线程名: " + Thread.currentThread().getName() + ", 任务 " + name + " is running!");
            Thread.sleep(200);
        } catch (InterruptedException e) {
 
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
 
        //线程池
        ExecutorService pools = new ThreadPoolExecutor(
                1,
                1,
                1,
                TimeUnit.SECONDS,
                new ArrayBlockingQueue<>(1),
                Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.CallerRunsPolicy());

        ThreadPoolExecutorTest run = null;
        // 循环创建线程
        for (int i = 0; i < 5; i++) {
 
            run = new ThreadPoolExecutorTest("" + i);
            // 将任务添加到线程池中
            pools.execute(run);
        }

        //关闭线程池
        pools.shutdown();
    }
}

 

3、线程池处理Callable

ExecutorService方法解释
void execute(Runnable command)执行任务/命令,没有返回值,一般用来执行 Runnable 任务
Future<T> submit(Callable<T> task)执行任务,返回未来任务对象获取线程结果,一般拿来执行 Callable 任务
void shutdown()等任务执行完毕后关闭线程池
List<Runnable> shutdownNow()立刻关闭,停止正在执行的任务,并返回队列中未执行的任务

 

import java.util.concurrent.Callable;

public class MyCallable implements Callable {
 
    private String name;

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

    @Override
    public Object call() throws Exception {
 
        for (int i = 0; i < 10; i++) {
 
            System.out.println(Thread.currentThread().getName() + name + " " + i);
        }
        return true;
    }
}
import java.util.concurrent.*;

public class ThreadPoolExecutorTest {
 

    public static void main(String[] args) throws ExecutionException, InterruptedException {
 
        //创建线程池
        ExecutorService pools = Executors.newFixedThreadPool(3);

        MyCallable myCallable1 = new MyCallable(" hadoop");
        MyCallable myCallable2 = new MyCallable(" flink");
        MyCallable myCallable3 = new MyCallable(" spark");

        //提交执行
        Future<Boolean> sb1 = pools.submit(myCallable1);
        Future<Boolean> sb2 = pools.submit(myCallable2);
        Future<Boolean> sb3 = pools.submit(myCallable3);

        //获取结果
        boolean b1 = sb1.get();
        boolean b2 = sb2.get();
        boolean b3 = sb3.get();

        System.out.println(b1);
        System.out.println(b2);
        System.out.println(b3);

        // 关闭线程池,如不关闭,线程池会一直运行
        pools.shutdown();
    }

}

4、Callable和Runnable接口的区别

Callable接口中的Call方法有返回值,Runnable接口中的Run方法没有返回值

Callable接口中的Call方法有声明异常,Runnable接口中的Run方法没有异常

Ubuntu20.04实时内核补丁PREEMPT_RT编译与安装全流程解析 本文详细解析了在Ubuntu20.04系统上编译与安装实时内核补丁PREEMPT_RT的全流程。从内核与补丁版本匹配、编译环境准备,到内核配置、编译排错,再到最终安装、验证与进阶优化,提供了手把手的实战指南,旨在帮助机器人、工业控制等对实时性有苛刻要求的开发者构建低延迟、高确定性的Linux系统。 阅读详情

相关推荐

语音AI Agent落地实战:从ASR-NLP-TTS到多通道协同决策

语音AI Agent并非简单的自动语音识别(ASR)、自然语言处理(NLP)和文本转语音(TTS)三模块串联,而是在真实场景中需兼顾实时性、鲁棒性与隐私合规的端到端交互系统。其核心原理在于打破‘文本中间态’依赖,通过声学-文本-上下文多通道协同决策,融合原始音频特征、N-best置信度与设备环境信号,实现动态意图推演。技术价值体现在低延迟(如120ms离线唤醒)、高抗噪(-5dB SNR下WER≤25%)及强可控性(断网降级、本地热更新)。典型应用场景覆盖车载语音、智能家居与银行网点等边缘受限环境,尤其适用

weixin_29065959的博客 330

java进阶(二):多线程

1、多线程的目的 即“最大限度的利用CPU资源”,当某一线程的处理不需要占用CPU而只和I/O等资源打交道时,让需要占用CPU资源的其他线程有机会获得CPU资源。 2、创建线程 方法一: 通过继承Thread类创建线程 普通线程如果继承自Thread类,就成为了一个线程类,并可以通过该类的start方法来启动线程,执行线程代码。 *Thread类的子类可以直接实例化,但在子类中必须覆盖r...

编程之路 447

TSP、MTSP问题遗传算法详细解读及python实现

写在前面 遗传算法是一种求解NPC问题的启发式算法,属于仿生进化算法族的一员。仿生进化算法是受生物行为启发而发明的智能优化算法,往往是人们发现某种生物的个体虽然行为较为简单,但生物集群通过某种原理却能表现出智能行为。于是不同的人研究不同的生物行为原理,受到启发而发明出新的仿生进化算法。比如免疫优化算法,蚁群算法,模拟退火算法等,这些算法以后也会简单介绍。 本文的主题是遗传算法,该算法也是受到生物行为启发。物竞天择,适者生存,优胜劣汰,是该优化算法的核心思想。笔者在业务中需要用到遗传算法求解TSP问题,但是网

weixin_47675950的博客 9306

JAVA进阶(二)——多线程

线程(thread):是能够进行运算的最小单位。它被包含在之中,是中的实际运作单位。一条线程指的是中一个单一顺序的控制流(即一个独立运行的程序片段)。进程:执行程序的一次执行过程,它是一个动态的概念,是系统分配资源的单位。一个进程中可以并发多个线程,每条线程并行执行不同的任务。多线程能满足程序员编写高效率的程序来达到充分利用 CPU 的目的。

qq_51446461的博客 604

ERA5获取的风场数据转换为.dfs2文件

ERA5获取风场数据的具体步骤可以参考下面的文章下载好后应该是.nc格式的文件,想要读取或者转换成其他格式的文件可以安装下面步骤,本文介绍如何转换为.dfs2文件。

我的博客 1460

如何编写 Skill 实现自动化用例生成

Skill 本质上是一组结构化的指令和工具定义,它告诉 AI 模型在特定场景下应该遵循什么流程、调用哪些工具、输出什么格式的内容。元信息:名称、描述、版本等。指令(Instructions):定义 AI 的行为准则和任务流程。工具(Tools):AI 可以调用的外部能力,如文件读写、代码执行、API 请求等。上下文(Context):预设的输入输出格式或示例。编写一个用于自动生成测试用例的 Skill,核心在于定义清晰的指令流程和输出规范。

Cesare的博客 2712

【Java进阶】多线程(二)

心动不如行动

小新的博客 561

Matlab处理气象数据(六)数据的面积加权

由于地理投影导致导致每个像元实际地面面积不同,越靠近北极实际面积越小,越靠近赤道实际面积越大,如果不进行面积加权就简单平均,会导致温度较实际温度偏低。 用以下公式计算地理投影每个像元的面积: double pi = 3.1415926; double R = 6371007.181; //units - m double area = (pi/180.0)*R*R*fabs(sin(dLat1/180.0*pi) - sin(dLat2/180.0*pi)) * fabs(dLon1 - dLo

设计の诗 1万+

【Java进阶之多线程进阶】代码库(二)

生产者消费者.javaimport java.util.concurrent.LinkedBlockingQueue;public class LocalTest { public static void main(String[] args) { LinkedBlockingQueue<Object> list = new LinkedBlockingQueue<Objec

极客神殿 499

强化学习:从经典强化学习理解强化学习

1. 背景介绍 强化学习(Reinforcement Learning,RL)作为机器学习领域的重要分支,近年来取得了长足的进步。其核心思想是让智能体通过与环境的交互学习最优策略,从而最大化累积奖励。不同于监督学习和非监督学习,强化学习无需预先标注数据,而是通过试错的方式逐步学习,具有更强的适应性和泛化能力。

AI架构师小马 1807

手把手教你完成YOLOv8分类识别界面搭建,使用Qt6设计YOLOv8分类识别系统,前台系统+后台管理系统开发实战,全网最详细教程

本项目基于YOLOv8分类模型,结合PySide6框架开发了一套图形化分类识别系统,支持图片、视频和摄像头实时检测。系统包含以下功能: 分类识别模块:完成图像/视频目标分类,界面展示检测结果。 用户管理模块:支持登录注册、头像修改、密码重置等功能。 AI问答模块:集成DeepSeek大模型接口,实现流式输出对话。 后台管理系统(第二版新增):管理员可管理用户信息及个人中心。 系统采用MySQL数据库存储用户数据,并提供完整的UI界面与交互逻辑。代码已开源,适用于毕业设计或快速部署场景。

在职AI算法工程师,擅长计算机视觉,YOLO目标检测、分割等,擅长web、pyqt界面可视化,好内容持续更新中,来这里跟大家一起学习,共同进步 827

java多线程进阶(二)同步锁

结合JVM,详细阐述了无锁,偏向锁轻量级锁,重量级锁之间的转化关系

jiayibingdong的博客 1363

语音信号的AGC自适应增益调整matlab仿真

语音信号的自动增益控制(Automatic Gain Control,AGC)是音频处理领域中的一项重要技术。其核心功能是实时调整输入信号的幅度,使其保持在一定范围内,以优化输出信号的质量。AGC广泛应用于语音通信、语音识别、音频录制和播放等领域,旨在解决输入信号幅度波动问题,确保输出信号的稳定性和清晰度。一、AGC的基本原理1.1 幅度调整自动增益控制的基本原理是根据输入信号的幅度动态地调整系统的增益。

平时工作较为繁忙,私信消息一般晚上回复,谢谢大家~~ 927

Java多线程之进阶篇(二)

接下来,我们继续学习Java多线程之进阶篇。Java多线程之进阶篇(一)介绍了线程池的相关内容,让我们大致对线程池有了初步的整体的认识,但是具体到稍微深入的知识点还是有点懵,这一篇主要介绍JUC的原子类。 在Java SE5 中java.util.concurrent.atomic包下提供了一系列支持无锁线程安全修改操作的基础变量。这些原子类是对volatile机制的扩展,并提供下面形式的原子性...

Tomdogs的专栏 4272

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

Java EE 进阶--多线程(二)

一、JUC(java.util.concurrent) 的常见类 1.1 信号量 Semaphore 1.2CountDownLatch 1.3 CyclicBarrier -循环栅栏 二、线程安全的集合类 2.1多线程环境使用 ArrayList 2.2 多线程环境使用队列 2.3 多线程环境使用哈希表 三、死锁 3.1死锁是什么 3.2 如何避免死锁 3.3 避免死锁的解决方案 四、ThreadLocal

qq_53332052的博客 576

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

Java多线程编程——进阶篇二

一、线程的交互 a、线程交互的基础知识 线程交互知识点需要从java.lang.Object的类的三个方法来学习: void notify() 唤醒在此对象监视器上等待的单个线程(notify()方法调用的时候,锁并没有被释放)。void notifyAll() 唤醒在此对象监视器上等待的所有线程。void wait()...

weixin_30657999的博客 121

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

Java进阶(二)--多线程及线程应用

1.1.线程的概念 进程:在多任务系统中,每个独立执行的程序称为进程 线程:一个进程中可以包含一个或多个线程,一个线程就是一个程序内部的一条执行线索 当程序启动时,就自动产生一个线程,主函数main就是在这个线程上运行的。前面所讲的例子都是单线程的 创建多线程有两种方法:继承Thread类和实现Runnable接口 1.1.1 线程的生命周期 1、 新建状态 当一个线程对象被创建后,线程就处于新建状态。在新建状态中的线程对象从严格意义上看还只是一个普通的对象,它还不是一个独立的线程。处于新建状态中的线程被调

baidu_41761770的博客 239

【Java EE初阶十一】多线程进阶二(CAS等)

本篇内容主要讲解了多线程中关于cas和juc的相关知识点

2202_76101487的博客 1829

Java SE 进阶复习(二)多线程

1、并行和并发有什么区别? 并行是指两个或者多个事件在同一时刻发生;而并发是指两个或多个事件在同一时间间隔发生。 并行是在不同实体上的多个事件,并发是在同一实体上的多个事件。 在一台处理器上“同时”处理多个任务,在多台处理器上同时处理多个任务。如hadoop分布式集群。 所以并发编程的目标是充分的利用处理器的每一个核,以达到最高的处理性能。 2、同步和异步有何异同,在什么情况下分别使用他们? ...

差不多先生 369

多线程进阶(二):JUC (java.util.concurrent)

java.util.concurrent

2401_83595513的博客 2645

JAVA从菜鸟到进阶(六)——多线程基础二 懒汉式在多线程时的优化及死锁问题

一 我们知道了一般方法的锁是this(调用对象) 而静态方法的锁是什么呢? package Test; class Test implements Runnable { private int flag=0; Object obj=new Object(); private static int num=100; public void run() { while(t...

weixin_43752167的博客 225

Java SE ——【多线程进阶知识】)(二)

线程的深入理解一、线程池1. 创建池原因2. 创建线程池二、线程安全的集合1. List集合 + Queue队列(1)List集合(2)Queue接口(队列)ConcurrentLinkedQueueBlockingQueue接口(阻塞队列)2. Set集合3. Map集合 一、线程池 1. 创建池原因 问题 ● 线程是宝贵的内存资源、单个线程约占1MB空间,过多分配易造成内存溢出。 ● 频繁的创建及销毁线程会增加虚拟机回收频率、资源开销,造成程序性能下降。 线程池 ● 线程容器,可设定线程分配的数量上限。

Nigori_gjh的博客 358

Java 第22天 高级进阶篇 多线程实现Runnable接口 (二.)

写在前言 : 知识是自己的,学习资源是共享的:B站是最好的也是全面滴。Good 1 、现在出去面试,面试官老是会问你一句话Java 怎么样? 不管是大数据岗位还是数据库都会问一句。 回来痛下决心,决定探索下这门语言的精髓,大数据很多框架也都是Java 写的,的确懂一门语言,比较稳妥。路也宽敞!!!不然就和吃饭没筷子,那么尴尬。把每天学习到的 Java知识分享到这里会。直到能自己写个复杂一点Dome得出来。 2、为了监督自己探索这门语言的动力与决心。特此这段话放到前面!!! 3、挑战下自己 到底是笨 还是学.

禧年 180

JAVA进阶学习-多线程基础详解(二)-同步

距离第一篇博客过了半个多月之后,我又回来了,前段时间因为要过年,所以很忙,到处走亲戚,相当悲催,今天终于有时间来更新博客了。   之前有些朋友读了第一篇博客之后说我写的有点晦涩,不够通俗易懂,想了一下言之有理,决定在以后的博客里换个风格,总之大家一起共勉吧,我也不是什么大神,有啥问题大家一定要替出来,本人有则改之,无则加勉!   之前的一篇博客里给大家介绍和分析了创建线程的两种方法,这篇博

小白的JAVA之路 722

【Java进阶】多线程&高并发(二)<线程安全问题>

非线程安全主要是指多个线程对同一个对象的实例变量进行操作时,会出现值被更改,但是值不同步的问题原子性、可见性和有序性原子(Atomic)就是不可分割的意思原子操作的不可分割有两层的含义① 访问(读/写)某个共享变量的操作从其他线程来看,该操作要么已经执行完毕,要么尚未发生,即其他线程是看不到当前操作的中间结果②访问同一组共享变量的原子操作是不能够交叉的。比如:现实生活中从ATM机取款,对于用户来说,要么操作成功,用户拿到钱,余额减少,增加一条交易记录;要么没拿到钱,相当于取款操作没有发生。

行为产生结果 314
上一篇: 硬核!阿里自爆虐心万字面试手册,Github上获赞89.7K
下一篇: Java 多线程:并发编程的三大特性
java_lujj
博客等级 码龄4年 18粉丝 152原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值