JUC详解 | JUC概述

article/2025/10/12 6:22:41

JUC详解 | JUC概述及其基础知识准备

  • 前言
  • 一、1. JUC概述及基础知识准备
    • 1.JUC是什么?
    • 2. 进程和线程
    • 3. 并行和并发
    • 4. wait/sleep的区别
    • 5.创建线程回顾
    • 6. lambda表达式
      • 6.1 什么是lambda表达式
      • 6.2 案列
      • 6.3函数式接口
      • 6.4 小结
    • 7. synchronized回顾
    • 8. synchronized的8锁问题
  • 问题
  • 总结


前言

本篇文章将对JUC进行详细讲解,码字不易,希望对大家有所帮助。


提示:以下是本篇文章正文内容,下面案例可供参考

一、1. JUC概述及基础知识准备

1.JUC是什么?

在 Java 5.0 提供了 java.util.concurrent(简称JUC)包,在此包中增加了在并发编程中很常用的工具类。此包包括了几个小的、已标准化的可扩展框架,并提供一些功能实用的类,没有这些类,一些功能会很难实现或实现起来冗长乏味。

参照JDK文档:
在这里插入图片描述

2. 进程和线程

进程:进程是一个具有一定独立功能的程序关于某个数据集合的一次运行活动。它是操作系统动态执行的基本单元,在传统的操作系统中,进程既是基本的分配单元,也是基本的执行单元。

线程:通常在一个进程中可以包含若干个线程,当然一个进程中至少有一个线程,不然没有存在的意义。线程可以利用进程所拥有的资源,在引入线程的操作系统中,通常都是把进程作为分配资源的基本单位,而把线程作为独立运行和独立调度的基本单位,由于线程比进程更小,基本上不拥有系统资源,故对它的调度所付出的开销就会小得多,能更高效的提高系统多个程序间并发执行的程度。

生活实例:

​ 使用QQ,查看进程一定有一个QQ.exe的进程,我可以用qq和A文字聊天,和B视频聊天,给C传文件,给D发一段语言,QQ支持录入信息的搜索。

​ 大四的时候写论文,用word写论文,同时用QQ音乐放音乐,同时用QQ聊天,多个进程。

​ word如没有保存,停电关机,再通电后打开word可以恢复之前未保存的文档,word也会检查你的拼写,两个线程:容灾备份,语法检查

3. 并行和并发

并发:同一时刻多个线程在访问同一个资源,多个线程对一个点

​ 例子:小米9今天上午10点,限量抢购

​ 春运抢票

​ 电商秒杀…

并行:多项工作一起执行,之后再汇总

​ 例子:泡方便面,电水壶烧水,一边撕调料倒入桶中

4. wait/sleep的区别

功能都是当前线程暂停,有什么区别?
wait:放开手去睡,放开手里的锁
sleep:握紧手去睡,醒了手里还有锁
wait是Object的方法,sleep是thread的方法

5.创建线程回顾

创建线程常用两种方式

  1. 继承Thread:java是单继承,资源宝贵,要用接口方式
  2. 实现Runable接口

继承Thread抽象类:

public class MyThread extends Thread
new MyThread().start();

实现Runnable接口的方式:
1. 新建类实现runnable接口。这种方法会新增类,有更好的方法

class MyRunnable implements Runnable//新建类实现runnable接口
new Thread(new MyRunnable(), name).start // 使用Rannable实现类创建进程,name是线程名

2.匿名内部类:

new Thread(new Runnable() {@Overridepublic void run() {// 调用资源方法,完成业务逻辑}
}, "your thread name").start();

6. lambda表达式

之前说了Runnable接口的两种实现方式,其实还有第三种:

  1. 创建类实现Runnable接口
  2. 编写匿名内部类实现Runnable接口
  3. lambda表达式:这种方法代码更简洁精炼\
new Thread(() -> {}, "your thread name").start();

6.1 什么是lambda表达式

Lambda 是一个匿名函数,我们可以把 Lambda表达式理解为是一段可以传递的代码(将代码像数据一样进行传递)。可以写出更简洁、更灵活的代码。作为一种更紧凑的代码风格,使Java的语言表达能力得到了提升。

Lambda 表达式在Java 语言中引入了一个新的语法元素和操作符。这个操作符为 “->” , 该操作符被称为 Lambda 操作符或剪头操作符。它将 Lambda 分为两个部分:

  • 左侧:指定了 Lambda 表达式需要的所有参数
  • 右侧:指定了 Lambda 体,即 Lambda 表达式要执行的功能

6.2 案列

在一个方法中调用接口中的方法:传统写法

interface Foo {public int add(int x, int y);
}public class LambdaDemo {public static void main(String[] args) {Foo foo = new Foo() {@Overridepublic int add(int x, int y) {return x + y;}};System.out.println(foo.add(10, 20));}
}

接下来,要用lambda表达式改造。其实是改造main方法

public static void main(String[] args) {Foo foo = (int x, int y)->{return x + y;};System.out.println(foo.add(10, 20));
}

改造口诀:拷贝小括号(),写死右箭头->,落地大括号{…}

6.3函数式接口

lambda表达式,必须是函数式接口,必须只有一个抽象方法,如果接口只有一个方法java默认它为函数式接口
为了正确使用Lambda表达式,需要给接口加个注解:@FunctionalInterface。如有两个方法,立刻报错。

Runnable接口为什么可以用lambda表达式?

@FunctionalInterface
public interface Runnable {/*** When an object implementing interface <code>Runnable</code> is used* to create a thread, starting the thread causes the object's* <code>run</code> method to be called in that separately executing* thread.* <p>* The general contract of the method <code>run</code> is that it may* take any action whatsoever.** @see     java.lang.Thread#run()*/public abstract void run();
}

发现Runnable接口上有一个注解:@FunctionalInterface

并且该接口只有一个方法:run()方法
其实,函数式接口必须只有一个方法,这个描述并不准确,它还允许有default方法和静态方法。

例如,在Foo接口中,又添加了sub方法和mul方法:

interface Foo {public int add(int x, int y); // 抽象方法default int sub(int x, int y){ // default方法return x - y;}public static int mul(int x, int y){ // 静态方法return x * y;}
}public class LambdaDemo {public static void main(String[] args) {Foo foo = (int x, int y)->{  // lambda表达式实现抽象方法return x + y;};System.out.println(foo.add(10, 20)); // 调用抽象方法System.out.println(foo.sub(30, 15)); // 调用default方法System.out.println(Foo.mul(10, 50)); // 通过Foo调用静态方法}
}

6.4 小结

lambda表达式实现接口的前提是

有且只有一个抽象方法,可以选择@FunctionalInterface注解增强函数式接口定义

改造口诀

拷贝小括号(形参列表),写死右箭头 ->,落地大括号 {方法实现}

7. synchronized回顾

多线程编程模板上

线程 操作 资源类 , :线程要操作的实体对象就叫资源类
高内聚:功能上讲:每个功能连接的非常紧密。
低耦合:模块上讲:

实现步骤:

  1. 创建资源类
  2. 资源类里创建同步方法、同步代码块
  3. 多线程调用

例子:卖票程序
创建工程,并添加了一个SaleTicket.java
在这里插入图片描述
内容如下:

class Ticket {private Integer number = 20;//用在方法上,叫同步方法public synchronized void sale(){if (number <= 0) {System.out.println("票已售罄!!!");return;}//try {System.out.println(Thread.currentThread().getName() + "开始买票,当前票数:" + number);Thread.sleep(200);System.out.println(Thread.currentThread().getName() + "买票结束,剩余票数:" + --number);} catch (InterruptedException e) {e.printStackTrace();}}
}// 在main方法中创建多线程方法,测试卖票业务
public class SaleTicket {public static void main(String[] args) {Ticket ticket = new Ticket();new Thread(() -> {for (int i = 0; i < 30; i++) {ticket.sale();}}, "AAA").start();new Thread(() -> {for (int i = 0; i < 30; i++) {ticket.sale();}}, "BBB").start();new Thread(() -> {for (int i = 0; i < 30; i++) {ticket.sale();}}, "CCC").start();}
}

8. synchronized的8锁问题

看下面这段儿代码,回答后面的8个问题:

class Phone {public synchronized void sendSMS() throws Exception {//TimeUnit.SECONDS.sleep(4);System.out.println("------sendSMS");}public synchronized void sendEmail() throws Exception {System.out.println("------sendEmail");}public void getHello() {System.out.println("------getHello");}}public class Lock_8 {public static void main(String[] args) throws Exception {Phone phone = new Phone();Phone phone2 = new Phone();new Thread(() -> {try {phone.sendSMS();} catch (Exception e) {e.printStackTrace();}}, "AA").start();Thread.sleep(100);new Thread(() -> {try {phone.sendEmail();//phone.getHello();//phone2.sendEmail();} catch (Exception e) {e.printStackTrace();}}, "BB").start();}
}

问题

多线程的8个问题:

  1. 标准访问,先打印短信还是邮件
  2. 停4秒在短信方法内,先打印短信还是邮件
  3. 普通的hello方法,是先打短信还是hello
  4. 现在有两部手机,先打印短信还是邮件
  5. 两个静态同步方法,1部手机,先打印短信还是邮件
  6. 两个静态同步方法,2部手机,先打印短信还是邮件
  7. 1个静态同步方法,1个普通同步方法,1部手机,先打印短信还是邮件
  8. 1个静态同步方法,1个普通同步方法,2部手机,先打印短信还是邮件

总结

synchronized实现同步的基础:Java中的每一个对象都可以作为锁。具体表现为以下3种形式:

  1. 对于普通同步方法,锁是当前实例对象。
  2. 对于静态同步方法,锁是当前类的Class对象。
  3. 对于同步方法块,锁是Synchonized括号里配置的对象

当一个线程试图访问同步代码块时,它首先必须得到锁,退出或抛出异常时必须释放锁。

也就是说:

​ 如果一个实例对象非静态同步方法获取锁后,该实例对象的其他非静态同步方法必须等待获取锁的方法释放锁后才能获取锁;可是不同实例对象的非静态同步方法因为用的是不同对象的锁,所以毋须等待其他实例对象的非静态同步方法释放锁,就可以获取自己的锁。

所有的静态同步方法用的是同一把锁——类对象本身。不管是不是同一个实例对象,只要是一个类的对象,一旦一个静态同步方法获取锁之后,其他对象的静态同步方法,都必须等待该方法释放锁之后,才能获取锁。

​ 而静态同步方法(Class对象锁)与非静态同步方法(实例对象锁)之间是不会有竞态条件的。


http://chatgpt.dhexx.cn/article/bEEk23Dd.shtml

相关文章

juc_lock

一个不是juc一个是juc情况 class Data2{private int number 0;Lock lock new ReentrantLock();Condition condition lock.newCondition();public void increment() throws Exception{lock.lock();try {while (number ! 0){condition.await();}number ;System.out.println(T…

JUC基础(周阳老师笔记

目录 一、JMM1.volatile2.加载代码练习&#xff1a; 二、JUC基础1.什么是进程/线程&#xff0c;并发/并行进程/线程并发/并行 2.线程的状态3.线程 操作 资源类4.Lambda表达式jdk8以后的interface 5.判断/干活/通知6.防止虚假唤醒(while not if)7.标志位lock精准通知condition 8…

什么是JUC

什么是JUC JUC指的是&#xff1a;Java里的三个包 java.util.concurrentjava.util.concurrent.atomic&#xff1a;原子性java.util.concurrent.locks&#xff1a;lock锁 回顾线程和进程 进程 程序执行的一次过程&#xff0c;一个进程包含一个或多个线程。进程是资源分配的单位…

Java - JUC详解

目录 一、了解和JUC相关的概念 二、Java线程 三、线程共享模型 一、了解和JUC相关的概念 1.1 什么是JUC&#xff1f; JUC是java.util.concurrent包的简称&#xff0c;在Java5.0添加&#xff0c;目的就是为了更好的支持高并发任务。让开发者进行多线程编程时减少竞争条件和…

JUC线程池

一、JUC介绍 java.util.concurrent包&#xff08;简称&#xff1a;JUC&#xff09;。JUC主要是让开发者在多线程编程中更加简单、方便一些。 通过JDK内置了一些类、接口、关键字&#xff0c;补充完善了JDK对于并发编程支持的“短板”。 主要功能&#xff1a;&#xff08;1&am…

JUC

&#xff08;尚硅谷笔记&#xff09; Java JUC 简介  在 Java 5.0 提供了 java.util.concurrent &#xff08;简称 JUC &#xff09;包&#xff0c;在此包中增加了在并发编程中很常用 的实用工具类&#xff0c;用于定义类似于线程的自定义子 系统&#xff0c;包括线程池、异…

JUC基础知识(个人总结)

声明: 1. 本文为我的个人复习总结, 并非那种从零基础开始普及知识 内容详细全面, 言辞官方的文章 2. 由于是个人总结, 所以用最精简的话语来写文章 3. 若有错误不当之处, 请指出 一. 前置基础: IO 操作不占用 cpu, 只是我们一般拷贝文件使用的是【…

1、JUC概述

1.1 什么是JUC 在Java中&#xff0c;线程部分是一个重点&#xff0c;本篇文章说的JUC 也是关于线程的。JUC就是java.util .concurrent工具包的简称。这是一个处理线程的工具包&#xff0c;JDK1.5开始出现的。 1.2 线程和进程的概念 进程和线程 进程&#xff08;Process&…

JUC基础【万字篇】

JUC 1、什么是JUC JUC&#xff1a;指的是java.util三个并发编程工具包 java.util.concurrentjava.util.concurrent.atomicjava.util.concurrent.locks 实现多线程的四种方式&#xff1a; 继承Thread类实现Runnable接口实现Callable接口线程池 业务&#xff1a;普通的线程代…

java--JUC快速入门(彻底搞懂JUC)

java–JUC快速入门&#xff08;彻底搞懂JUC&#xff09; 文章目录 java--JUC快速入门&#xff08;彻底搞懂JUC&#xff09;1、学习多线程之前需要知道的一些概念。2、JUC的结构3、Lock锁(重点)4、集合类不安全5、Callable()6、常用的辅助类7、读写锁8、阻塞队列9、线程池 1、学…

Dbeaver做数据迁移

1、选择源头数据库的表、鼠标右击、选择导出数据 2、在数据转化弹框中&#xff0c;双击 ‘数据库&#xff0c;数据表’ 那一栏 3、选择目标数据库&#xff0c;调整字段类型映射关系 4、调整字段的映射关系 目前遇到的字段类型&#xff0c;只有 int&#xff0c;bigint 转 num…

dbeaver工具连接达梦数据库

、一 概述 DBeaver 是一个基于 Java 开发&#xff0c;免费开源的通用数据库管理和开发&#xff0c;DBeaver 采用 Eclipse 框架开发&#xff0c;支持插件扩展&#xff0c;并且提供了许多数据库管理工具&#xff1a;ER 图、数据导入/导出、数据库比较、模拟数据生成等&#xff0…

DBeaver 格式化sql

有时候我们拿到了一条sql语句是长长的&#xff0c;非常不容易阅读&#xff0c;这时我们就想说哪里可以格式下sql代码。 方法有很多种&#xff0c;这里我就用Dbeaver来格式化sql。 ①打开Dbeaver ②复制sql代码到SQL编辑器中&#xff0c;并选中 ③按ctrlshiftF&#xff0c;即…

【DBeaver】常用自定义设置

文章目录 背景一、用户界面设置1.1、22.3.4版本1.1.1、SQL编辑器-字体设置1.1.2、查询结果-字体设置 1.2、23.0.0版本1.2.1、应用字体&#xff08;导航栏等&#xff09;1.2.2、文本字体&#xff08;SQL输出、文本编辑器等&#xff09; 二、常规设置2.1、连接类型设置/环境设置 …

DBeaver导入Excel数据

目录 前言 导入准备 ​导入步骤 1.选中数据库表&#xff0c;右键&#xff0c;然后点击导入数据 2.双击CSV,选择待导入的文件 3.修改编码格式&#xff08;可选&#xff0c;不乱码不用&#xff09; 4.点击下一步&#xff0c;修改列的类型 5.一直下一步&#xff0c;点击…

Dbeaver基本使用

1&#xff1a;与plsql相比&#xff0c;Dbeaver没有右击直接查看表注释的功能&#xff0c;但是Dbeaver提供了一个“打开声明”的功能&#xff0c;里面可以查看一些比较实用的内容&#xff1a;表列注释、创建该表的create语句&#xff1a; 2&#xff1a;在一般开发的情况下&#…

【大数据】Hive可视化工具dbeaver

Hive可视化工具dbeaver 1、dbeaver基本介绍 dbeaver是一个图形化的界面工具&#xff0c;专门用于与各种数据库的集成&#xff0c;通过dbeaver我们可以与各种数据库进行集成通过图形化界面的方式来操作我们的数据库与数据库表&#xff0c;类似于我们的sqlyog或者navicat。 2、…

DBeaver安装及使用手册

一、DBeaver安装 1、在[DBeaver官网](https://dbeaver.io/download)进行数据库工具下载&#xff0c;下载好后双击运行2、选择语言后&#xff0c;点击OK 3、点击下一步 4、接受许可 5、选择可使用者&#xff0c;然后点击下一步 6、选择组件&#xff0c;一般选择默认即可 7…

DBeaver-Driver-All ( DBeaver驱动包,所有JDBC驱动整合包)

DBeaver-Driver-All DBeaver-Driver-All ( DBeaver驱动包 )整合所有DBeaver的JDBC驱动包&#xff0c;供DBeaver使用&#xff0c;无需每次都搜索和下载&#xff0c;只需clone本项目即可&#xff0c;一个包包含几乎所有的驱动&#xff0c;如果有缺漏的驱动欢迎提Issue补充。 DBe…

DBeaver 下载安装

1 下载地址(我下载的 Windows版本&#xff0c;根据系统需要选择版本) Releases dbeaver/dbeaver GitHubFree universal database tool and SQL client. Contribute to dbeaver/dbeaver development by creating an account on GitHub.https://github.com/dbeaver/dbeaver/rel…