【JUC】并发编程学习笔记(二)

news2024/11/16 11:29:56

JUC并发编程

  • 五、多线程锁
    • 5.1、synchronized实现同步的基础
    • 5.2、公平锁与非公平锁
    • 5.3、可重入锁
    • 5.4、死锁
      • 5.4.1、概念
      • 5.4.2、案例
      • 5.4.3、查看死锁
  • 六、Callable接口
    • 6.1、概述
    • 6.2、FutureTask概述和原理
    • 6.3、案例
  • 七、辅助类
    • 7.1、减少计数CountDownLatch
    • 7.2、循环棚栏CyclicBarrier
    • 7.3、信号灯Semaphore

五、多线程锁

5.1、synchronized实现同步的基础

Java中的每一个对象都可以作为锁。
具体表现为以下3种形式。

  • 对于普通同步方法,锁是当前实例对象。
  • 对于静态同步方法,锁是当前类的class对象。
  • 对于同步方法块,锁是synchonized括号里配置的对象

5.2、公平锁与非公平锁

//创建非公平锁
//可能一个线程吃掉所有任务 其他线程被“饿死” 但效率高
private final ReentrantLock lock = new ReentrantLock(false);
//创建公平锁
//每个线程都领到任务 但效率降低
private final ReentrantLock lock = new ReentrantLock(true);

5.3、可重入锁

同一个线程在外层方法获取锁的时候,再进入该线程的内层方法会自动获取锁(前提是锁对象得是同一个对象),不会因为之前已经获取过锁还没有释放而发生阻塞

class RLock {
    public synchronized void add(){
        add();
    }
}
public class Demo06 {
    public static void main(String[] args) {
        new RLock().add();
    }
}

此时不会堵塞 只会栈溢出java.lang.StackOverflowError

5.4、死锁

5.4.1、概念

两个或者两个以上进程在执行过程中,因为争夺资源而造成一种互相等待的现象。如果没有外力干涉,他们无法再执行下去。
在这里插入图片描述

产生死锁原因:

  1. 系统资源不足
  2. 进程运行推进顺序不合适
  3. 资源分配不当

5.4.2、案例

import java.util.concurrent.TimeUnit;

public class DeadLock {

    static Object o1=new Object();
    static Object o2=new Object();

    public static void main(String[] args) {
        new Thread(()->{
            synchronized (o1){
                System.out.println(Thread.currentThread().getName()+"持有o1,试图获取o2");
                try {
                    TimeUnit.SECONDS.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                synchronized (o2){
                    System.out.println(Thread.currentThread().getName()+"获取o2");
                }
            }
        },"aa").start();

        new Thread(()->{
            synchronized (o2){
                System.out.println(Thread.currentThread().getName()+"持有o2,试图获取o1");
                try {
                    TimeUnit.SECONDS.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                synchronized (o1){
                    System.out.println(Thread.currentThread().getName()+"获取o1");
                }
            }
        },"bb").start();
    }
}

5.4.3、查看死锁

  1. jps
    先输入jps -l找到进程号
  2. jstack
    jvm自带堆栈跟踪工具
    输入jstack 进程号在最后提示Found xxx deadlock.发现xx个死锁

在这里插入图片描述
在这里插入图片描述

六、Callable接口

6.1、概述

通过使用Runnable 创建线程。但是,Runnable 缺少的一项功能是,当线程终止时(即run ( )完成时),我们无法使线程返回结果。为了支持此功能,Java中提供了Callable接口。

RunnableCallable
是否有返回值
是否抛出异常
实现方法run()call()

6.2、FutureTask概述和原理

FutureTask类 实现了RunnableFuture接口,而RunnableFuture 继承了Runnable和Future接口,所以本质上 FutureTask是Runnable的一种实现。

6.3、案例

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

//比较Callable Runable
class MyThread1 implements Runnable{
    @Override
    public void run() {

    }
}
class MyThread2 implements Callable{
    @Override
    public Integer call() throws Exception {
        return 200;
    }
}
public class Demo1 {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        //创建Runable线程
        new Thread(new MyThread1(),"aa").start();

        //创建Callable线程
        //不能直接替换runnable的方式,因为Thread类的构造方法根本没有Callable.
        //FutureTask构造可以传递callable

        //创建FutureTask线程
        FutureTask<Integer> futureTask1=new FutureTask<>(new MyThread2());

        //lambda简化FutureTask线程
        FutureTask<Integer> futureTask2=new FutureTask<>(()->{
            System.out.println(Thread.currentThread().getName()+" in Callable");
            return 1024;
        });

        new Thread(futureTask2,"bb").start();
        while (!futureTask2.isDone()){
            System.out.println("wait");
        }
        System.out.println(futureTask2.get());
        System.out.println(futureTask1.get());
        System.out.println(Thread.currentThread().getName()+" over");
    }
}

七、辅助类

7.1、减少计数CountDownLatch

CountDownLatch类可以设置一个计数器,然后通过countDown方法来进行减1的操作,使用await方法等待计数器不大于0,然后继续执行await方法之后的语句。

  • CountDownLatch主要有两个方法,当一个或多个线程调用await方法时,这些线程会阻塞
  • 其它线程调用countDown方法会将计数器减1(调用countDown方法的线程不会阻塞)
  • 当计数器的值变为0时,因await方法阻塞的线程会被唤醒,继续执行

案例:6个同学陆续离开教室后才可以关门
正常写法

public class CountDownLatchDemo {
    public static void main(String[] args) {
        //6个同学陆续离开教室之后
        for (int i = 1; i <=6; i++) {
            new Thread(()->{
                System.out.println(Thread.currentThread( ).getName()+"号同学离开了教室");
            },String.valueOf(i)).start();
        }
        System.out.println(Thread.currentThread( ).getName()+"锁门了");
    }
}

会出现问题:
在这里插入图片描述
更改之后:

import java.util.concurrent.CountDownLatch;

public class CountDownLatchDemo {
    public static void main(String[] args) throws InterruptedException {

        //创建CountDownLatch
        CountDownLatch countDownLatch=new CountDownLatch(6);

        //6个同学陆续离开教室之后
        for (int i = 1; i <=6; i++) {
            new Thread(()->{
                System.out.println(Thread.currentThread( ).getName()+"号同学离开了教室");
                countDownLatch.countDown();
            },String.valueOf(i)).start();
        }
        //等待
        countDownLatch.await();
        System.out.println(Thread.currentThread( ).getName()+"锁门了");
    }
}

在这里插入图片描述

7.2、循环棚栏CyclicBarrier

允许一组线程全部等待彼此达到共同屏障点的同步辅助。循环阻塞在涉及固定大小的线程方的程序中很有用,这些线程必须偶尔等待彼此。屏障被称为循环 ,因为它可以在等待的线程被释放之后重新使用。

例子:集齐7颗龙珠就可以召唤神龙

import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;

public class CyclicBarrierDemo {
    //创建固定值
    private static final int NUMBER = 7;

    public static void main(String[] args) {
        CyclicBarrier cyclicBarrier=new CyclicBarrier(NUMBER,()->{
            System.out.println("已经集齐7颗龙珠,可以召唤神龙了");
        });
        for (int i = 1; i <=7; i++) {
            new Thread(()->{
                try {
                    System.out.println(Thread.currentThread( ) .getName()+"星龙被收集到了");
                    //等待
                    cyclicBarrier.await();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            },String.valueOf(i)).start();
        }
    }
}

在这里插入图片描述

7.3、信号灯Semaphore

一个单向隧道能同时容纳10个小汽车或5个卡车通过(1个卡车等效与2个小汽车), 而隧道入口记录着当前已经在隧道内的汽车等效比重. 比如1个小汽车和1个卡车, 则隧道入口显示3. 若隧道入口显示10表示已经满了. 当汽车驶出隧道之后, 隧道入口显示的数字则会相应的减小. 于这个示例相符合场景非常适合用信号量.

案例:抢车位,6部汽车3个停车位

import java.util.Random;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;

public class SemaphoreDemo {
    public static void main(String[] args) {
        Semaphore semaphore=new Semaphore(3);

        for (int i = 1; i <=6; i++) {
            new Thread(()->{
                try {
                    //抢占
                    semaphore.acquire();
                    System.out.println(Thread.currentThread( ) .getName()+"抢到了车位");
                    //设置随机停车时间
                    TimeUnit.SECONDS.sleep(new Random().nextInt(5));
                    System.out.println(Thread.currentThread( ) .getName()+"离开了车位");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }finally {
                    semaphore.release();
                }
            },String.valueOf(i)).start();
        }
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/56480.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

[HITCON CTF 2022] Superprime,rev Meow_way,BabySSS格基约减法,Secret共模攻击模未知

目录 Superprime Reverse Meow_way BabySSS Secret Superprime 这个题5层RSA加密&#xff0c;很简单就是要带条件爆破5组p,q&#xff0c;一开始看错了&#xff0c;对为5组是一一对应的&#xff0c;回头发现后边两对不是对应的。 from Crypto.Util.number import getPrime,…

[附源码]Python计算机毕业设计Django旅游度假村管理系统

项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等等。 环境需要 1.运行环境&#xff1a;最好是python3.7.7&#xff0c;…

计算程序运行时间:计算或者不计算sleep()的两种情况perf_counter()和process_time()

【小白从小学Python、C、Java】 【计算机等级考试500强双证书】 【Python-数据分析】 计算程序运行时间&#xff1a; 计算或者不计算sleep()的两种情况 perf_counter()和process_time() [太阳]选择题 对下面描述错误的选项为&#xff1f; import time print(使用perf_counter…

[附源码]计算机毕业设计作业管理系统Springboot程序

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

【Matplotlib绘制图像大全】(二十四):Matplotlib为图像添加网格信息

前言 大家好,我是阿光。 本专栏整理了《Matplotlib绘制图像大全》,内包含了各种常见的绘图方法,以及Matplotlib各种内置函数的使用方法,帮助我们快速便捷的绘制出数据图像。 正在更新中~ ✨ 🚨 我的项目环境: 平台:Windows10语言环境:python3.7编译器:PyCharmMatp…

Mybatis练习(多条件查询)

Mybatis练习(多条件查询) 概述 功能实现的步骤&#xff1a; 编写接口方法 参数&#xff1a;所有查询条件结果&#xff1a;List 在映射配置文件中编写SQL语句 编写测试方法并执行 编写接口方法 在 BrandMapper 接口中定义多条件查询的方法。 而该功能有三个参数&#xf…

排序算法两万字总结(C语言实现)

文章目录前言一、排序的概念二、常见的排序算法排序实现的接口(1)插入排序基本思想1.直接插入排序1.1代码实现1.2直接插入排序特性总结2.希尔排序(缩小增量排序)2.1代码实现2.2希尔排序的特性总结(2)选择排序基本思想1.直接选择排序1.1代码实现1.2直接选择排序的特性总结2.堆排…

Sentinel服务保护

一&#xff0e;微服务雪崩问题&#xff1f; 微服务模块之间相互调用&#xff0c;因为调用(同步调用)链中的一个服务故障&#xff0c;引起整个链路都无法访问的情况 解决方案: 避免服务宕机&#xff1a;流量控制服务已经宕机&#xff1a;熔断降级Hystrix -----springcloud …

python中numpy创建数组

1. numpy数组的创建 1.1 使用array方法进行创建 数组是numpy中一种常见的格式&#xff0c;和列表类似&#xff0c;可以理解为矩阵&#xff0c;可以使用array方法进行获取 import numpy as np import random#使用numpy生成数组,得到ndarray的类型 t1 np.array([1,2,3,]) pri…

[附源码]计算机毕业设计springboot小太阳幼儿园学生管理系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

CMake 官方文档入门

对比官方文档练习 step1 基本起始点 一个基本的项目&#xff1a;从源文件构建可执行程序 文件目录如下 编写 CMakeLists.txt 如下&#xff1a; # cmake 要求的最小版本 cmake_minimum_required(VERSION 3.24) # 设置项目名称 可以设置版本号 project(Tutorial VERSION 1.0)…

【Docker】本地镜像与私有库:发布、拉取,图文展示全过程

Docker是基于Go语言实现的云开源项目。Docker的主要目标是**“Build&#xff0c;Ship and Run Any App,Anywhere”**。也就是通过对应用组件的封装、分发、部署、运行等生命周期的管理&#xff0c;使用户的APP&#xff08;可以是一个WEB应用或数据库应用等等&#xff09;及其运…

Linux环境MySQL数据库主从复制保姆级教程

文章目录1、环境准备1.1、安装MySQL1.2、设置root登录密码2、主库配置2.1、修改my.cnf2.2、重启数据库2.3、检验设置是否成功2.4、建立主从复制的账号3、从库配置3.1、配置my.cnf3.2、配置复制参数3.3、查看从库状态4、测试5、注意事项5.1、接口放行5.2、防火墙关闭5.3、Slave_…

Android Framework的框架描绘~

前言 写在前面&#xff1a; 1、有没有必要学习linux内核&#xff1f; 我认为是很有必要的。学习linux内核有助于我们加深对一些概念的理解&#xff0c;比如“进程”、“线程”。 2、有没有必要自己编译android源码&#xff1f; 非必须&#xff0c;可以直接用android studio查看…

【图表利剑】开发复杂Echarts时,visualMap视觉组件中属性seriesIndex必须用起来

一、背景 据说90%的可视化是用Echarts开发&#xff0c;没错&#xff0c;笔者也没例外&#xff0c;在新的开发项目中&#xff0c;遇到了这个开发神器Echarts&#xff0c;想要的功能就是在省份上显示动态效果图&#xff0c;比如涟漪。原来的功能已有范围视觉组件visualMap。 二…

【Matplotlib绘制图像大全】(十九):Matplotlib绘制等高线

前言 大家好,我是阿光。 本专栏整理了《Matplotlib绘制图像大全》,内包含了各种常见的绘图方法,以及Matplotlib各种内置函数的使用方法,帮助我们快速便捷的绘制出数据图像。 正在更新中~ ✨ 🚨 我的项目环境: 平台:Windows10语言环境:python3.7编译器:PyCharmMatp…

SAP ABAP——数据类型(四)【TYPE系列关键字】

&#x1f482;作者简介&#xff1a; THUNDER王&#xff0c;一名热爱财税和SAP ABAP编程以及热爱分享的博主。目前于江西师范大学会计学专业大二本科在读&#xff0c;同时任汉硕云&#xff08;广东&#xff09;科技有限公司ABAP开发顾问。在学习工作中&#xff0c;我通常使用偏后…

gitHub不能用密码推送了,必须要使用令牌

有一段时间没使用github去push项目了&#xff0c;今天push之后&#xff0c;根据提示输入账号密码&#xff0c;但是失败了&#xff0c;报错如下&#xff1a; support for password authentication was removed on August 13, 2021. remote: Please see https://docs.github.com…

【Swin Transformer原理和源码解析】Hierarchical Vision Transformer using Shifted Windows

目录前言一、动机和改进点二、整体架构&#xff1a;SwinTransformer三、输入设置&#xff1a;PatchEmbed四、4个重复的Stage&#xff1a;BasicLayer4.1、SwinTransformerBlock4.1.1、创建mask4.1.2、shift特征4.1.3、为shift后的特征划分窗口4.1.4、W-MSA VS SW-MSA4.2、PatchM…

Android APP 停止运行报错弹窗

一个APP经常性的报错,然后就会弹出一个"很抱歉,xxx已停止运行"这样的弹窗,在Android系统层临时将这个弹窗屏蔽.弹窗如下: 在没做过此类修改之前,不知到如何下手的情况下,请做如下几步: 在Android目录下全局搜索关键字"很抱歉",然后会有一个路径frameworks…