Java笔记-JUC基础

news2024/11/24 12:43:53

1、什么是JUC

JUC指的是java.util三个并发编程工具包

  • java.util.concurrent
  • java.util.concurrent.atomic
  • java.util.concurrent.locks

2、线程的几种状态

public enum State{
	NEW,//新建
	RUNNABLE,//准备就绪,等待资源
	BLOCKED,//阻塞
	WAITING,//一直等待
	TIMED_WAITING,//超时等待,过时不候
	TERMINATED;//终止,线程已经完成执行
}

在这里插入图片描述

3、wait和sleep的区别

1、来自不同的类
wait来自Object类,任何对象实例都能调用
sleep来自Thread类,是Thread的静态方法
2、锁的释放
wait会释放锁
sleep不需要占用锁,不会释放锁
3、使用范围、捕获异常不同
wait:必须在同步代码块中使用,不需要捕获异常
sleep:可以在任何地方使用,必须捕获异常

4、线程间通信

4.1 生产者和消费者

生产者与消费者是java并发环境下常见的设计模式,一个线程负责生产数据,一个线程负责消费数据,两个线程同时去操作这个变量,但是这是两个相互互斥的操作。
步骤:
(1)创建资源类,在资源类中创建属性和方法
(2)资源类的方法
判断等待-》业务逻辑-》通知唤醒
(3)创建多个线程,调用资源类的方法
(4)防止虚假唤醒
线程操作资源类-》判断干活-》通知,while防止虚假唤醒
虚假唤醒:线程可以被唤醒,而不会被通知,中断或超时
因此等待应该总是出现在循环中,如果条件不满足,则继续等待

实现方式1-synchronized


public class Mythread2 {
    public static void main(String[] args) {
        Resource resource = new Resource();//资源类
        //生产者
        new Thread(new Runnable() {
            @Override
            public void run() {
                try{
                    resource.increment();
                }catch (InterruptedException e){
                    e.printStackTrace();
                }

            }
        },"producer").start();
        //消费者
        new Thread(new Runnable() {
            @Override
            public void run() {
                try{
                    resource.decrement();
                }catch(InterruptedException e){
                    e.printStackTrace();
                }
            }
        },"consumer").start();
    }
}

class Resource{
    int number=1;
    public synchronized void  increment() throws InterruptedException{
        while(number!=0){//判断
            this.wait();
        }
        number++;//干活
        System.out.println(Thread.currentThread().getName()+"=>"+number);
        this.notifyAll();
    }
    public synchronized void decrement() throws InterruptedException{
        while (number==0){
            this.wait();
        }
        number--;
        System.out.println(Thread.currentThread().getName()+"=>"+number);
        this.notifyAll();
    }
}

实现方式2-JUC-lock

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class MyThread3 {
}

class Resource1{
    private int number=0;
    Lock lock=new ReentrantLock();
    Condition condition=lock.newCondition();
    public void increment()throws InterruptedException{
        lock.lock();
        try{
            while (number!=0){
                condition.await();
            }
            number++;
            System.out.println(Thread.currentThread().getName()+"=>"+number);
            condition.signalAll();
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            lock.unlock();
        }
    }

    public void decrement() throws InterruptedException{
        lock.lock();
        try{
            while(number==0){
                condition.await();
            }
            number--;
            System.out.println(Thread.currentThread().getName()+"=》"+number);
            condition.signalAll();
        }catch (InterruptedException e){
            e.printStackTrace();
        }finally {
            lock.unlock();
        }
    }
}

lock方式与synchronized的区别

与synchronized的区别:
lock中的condition可以实现精准定位
如下示例,实现了线程顺序按照A-B-C的顺序执行

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class MyThread3 {
    public static void main(String[] args) {
        Resource1 resource1=new Resource1();
        new Thread(new Runnable() {
            @Override
            public void run() {
                try{
                    for (int i=0;i<10;i++){
                        resource1.printA();
                    }
                }catch(InterruptedException e){
                    e.printStackTrace();
                }

            }
        },"A").start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                try{
                    for (int i=0;i<10;i++){
                        resource1.printB();
                    }
                }catch(InterruptedException e){
                    e.printStackTrace();
                }

            }
        },"B").start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                try{
                    for (int i=0;i<10;i++){
                        resource1.printC();
                    }

                }catch(InterruptedException e){
                    e.printStackTrace();
                }

            }
        },"C").start();
    }


}

class Resource1{
    private int number=1;
    Lock lock=new ReentrantLock();
    Condition condition1=lock.newCondition();
    Condition condition2=lock.newCondition();
    Condition condition3=lock.newCondition();
    public void printA()throws InterruptedException{
//        System.out.println(Thread.currentThread().getName()+"=>"+number);
        lock.lock();
        try{
            while (number!=1){
                condition1.await();
            }
            number=2;
            System.out.println(Thread.currentThread().getName()+"=>"+number);
            condition2.signalAll();
        }catch (InterruptedException e){
            e.printStackTrace();
        }finally {
            lock.unlock();
        }
    }
    public void printB()throws InterruptedException{
//        System.out.println(Thread.currentThread().getName()+"=>"+number);
        lock.lock();
        try{
            while (number!=2){
                condition2.await();
            }
            number=3;
            System.out.println(Thread.currentThread().getName()+"=>"+number);
            condition3.signalAll();
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            lock.unlock();
        }
    }
    public void printC()throws InterruptedException{
//        System.out.println(Thread.currentThread().getName()+"=>"+number);
        lock.lock();
        try{
            while (number!=3){
                condition2.await();
            }
            number=1;
            System.out.println(Thread.currentThread().getName()+"=>"+number);
            condition1.signalAll();
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            lock.unlock();
        }
    }
}

在这里插入图片描述

5、常用的辅助类

(1)CountDownLatch-减法计数器

用给定的数字进行初始化,等待所有线程执行完(await),才进行下一步。使用countDown方法使当前计数器到0,之后所有等待线程被释放。一次性操作,无法重置计数,如果需要重置计数,可以使用CyclicBarrier。

import java.util.concurrent.CountDownLatch;

public class CountDownLanch1 {
    public static void main(String[] args) throws InterruptedException{
  //  倒计时 起始为6 必须要执行任务的时候,再使用!
        CountDownLatch countDownLatch=new CountDownLatch(6);
        for (int i=0;i<6;i++){
            new Thread(new Runnable() {
                @Override
                public void run() {
                    System.out.println(Thread.currentThread().getName()+"->线程");
                    countDownLatch.countDown();//计数器-1
                }
            },String.valueOf(i)).start();
        }
        countDownLatch.await();//待计数器归零在向下执行
        System.out.println("线程全部执行完毕");
    }

}

在这里插入图片描述

2、CyclicBarrier(加法计数器)

线程加法,只有等到一定数量的线程都开启后,才进行下一步(执行run方法)
比如:集齐7颗龙珠,才能召唤神龙

import java.util.concurrent.CyclicBarrier;

public class CyclicBarrierDemo {
    public static void main(String[] args) {
        CyclicBarrier barrier=new CyclicBarrier(7,new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("集齐龙珠,召唤神龙");
            }
        }) );

        for(int i=1;i<=7;i++){
            final int temp=i;
            new Thread(new Runnable() {
                @Override
                public void run() {
                    System.out.println(Thread.currentThread().getName() + "第" + temp + "颗龙珠");
                    try{
                        barrier.await();//等待
                    }catch (Exception e){
                        e.printStackTrace();
                    }
                }
            },String.valueOf(i)).start();
        }

    }
}

在这里插入图片描述

3、Semaphore(信号量)

计数信号量,允许优先的多线程去访问公共资源,如:6个车抢3个停车位
原理:
semaphore.acquire(); //获得,如果已经满了,等待,等待被释放为止!

semaphore.release(); // 释放,会将当前的信号量释放+1,然后唤醒等待的线程!

作用:多个共享资源互斥的使用!并发限流,控制最大的线程数!

import java.sql.Time;
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(new Runnable() {
                @Override
                public void run() {
                    try{
                        semaphore.acquire();
                        System.out.println(Thread.currentThread().getName() + "抢到车位");
                        TimeUnit.SECONDS.sleep(3);
                        System.out.println(Thread.currentThread().getName()+"离开车位");
                    }catch(InterruptedException e){
                        e.printStackTrace();
                    }finally {
                        semaphore.release();
                    }
                }
            },String.valueOf(i)).start();
        }
    }
}

4.读写锁

写锁:独占锁
读锁:共享锁
读写锁:一个资源可以被多个读线程访问,或者被一个写线程访问,但是不能同时存在读写线程,读写互斥,读读是共享的

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

public class ReadWriteLockDemo {
    public static void main(String[] args) {
        MyCache myCache=new MyCache();
        //写线程
        for (int i=0;i<5;i++){
            final int temp=i;
            //写入
            new Thread(new Runnable() {
                @Override
                public void run() {
                    myCache.put(temp+"",""+temp);
                }
            },String.valueOf(i)).start();
        }
        //读线程
        for(int i=0;i<5;i++){
            final int temp=i;
            new Thread(new Runnable() {
                @Override
                public void run() {
                    System.out.println("获取"+temp+"缓存数据=="+myCache.get(temp+""));
                }
            },String.valueOf(i)).start();
        }
    }
}

class MyCache{
    private volatile Map<String,Object> map=new HashMap<>();
    private ReadWriteLock readWriteLock=new ReentrantReadWriteLock();
    //写存
    public void put(String key,Object value){
        readWriteLock.writeLock().lock();//写锁
        System.out.println(Thread.currentThread().getName()+"写入"+key);
        try{
            TimeUnit.MILLISECONDS.sleep(200);
            map.put(key,value);
        }catch (InterruptedException e){
            e.printStackTrace();
        }finally {
            readWriteLock.writeLock().unlock();//写完释放锁
        }
        System.out.println(Thread.currentThread().getName() + "写入OK");
    }

    //读取
    public Object get(String key){
        readWriteLock.readLock().lock();//加读锁
        Object object=null;
        try{
            System.out.println(Thread.currentThread().getName() + "读取" + key);
            object=map.get(key);
            System.out.println(Thread.currentThread().getName() + "读取OK");
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            readWriteLock.readLock().unlock();//释放读锁
        }
        return object;
    }
}


在这里插入图片描述

参考文章:

线程的5个状态
JUC基础

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

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

相关文章

vue脚手架 element-ui spring boot 实现图片上传阿里云 并保存到数据库

一.阿里云 注册登陆就不讲了&#xff0c;登陆进去后如下操作 1. 进入对象存储OSS 创建一个新的Bucket 随后点击新建的bucket 2.去访问RAM 前往RAM控制台 3.去创建用户 4.创建密匙 5.随后返回RAM控制台 给用户增加权限&#xff0c;文件上传所需权限&#xff0c;需要带含有…

LeetCode——1797. 设计一个验证系统

一、题目 你需要设计一个包含验证码的验证系统。每一次验证中&#xff0c;用户会收到一个新的验证码&#xff0c;这个验证码在 currentTime 时刻之后 timeToLive 秒过期。如果验证码被更新了&#xff0c;那么它会在 currentTime &#xff08;可能与之前的 currentTime 不同&am…

Java IO模型详解

文章目录Java IO模型详解一、I/O的定义1、计算机结构的视角2、应用程序的视角二、Java 中3种常见的 I/O 模型1、同步阻塞 I/O&#xff08;BIO&#xff09;2、同步非阻塞 I/O&#xff08;NIO&#xff09;★ I/O 多路复用模型3、异步非阻塞 I/O&#xff08;AIO&#xff09;Java I…

Flutter 小技巧之 3.7 更灵活的编译变量支持

今天我们聊个简单的知识点&#xff0c;在 Flutter 3.7 的 release-notes 里&#xff0c;有一个没有出现在 announcement 说明上的 change log &#xff0c;可能对于 Flutter 团队来说这个功能并不是特别重要&#xff0c;但是对于我个人而言&#xff0c;这是一个十分重要的能力补…

什么是模板方法模式?

在面向对象程序设计过程中&#xff0c;程序员常常会遇到这种情况&#xff1a;设计一个系统时知道了算法所需的关键步骤&#xff0c;而且确定了这些步骤的执行顺序&#xff0c;但某些步骤的具体实现还未知&#xff0c;或者说某些步骤的实现与具体的环境相关。例如&#xff0c;去…

阿里云国际服务器ECS特性与优势

阿里云国际服务器的 ECS 作为一种安全、可靠、灵活、可扩展的云计算服务&#xff0c;不仅可以减少运行和维护&#xff0c;而且可以提高运行和维护效率&#xff0c;使用户关注核心业务的创新。 阿里云国际服务器ECS优势一&#xff1a;产品丰富 阿里云国际云服务器 ECS 可以提供…

《MySql学习》 SQL 语句的更新过程

《MySql学习》 SQL 语句的更新过程 一.SQL查询语句的执行过程 上一篇博文记录了SQL查询语句的执行过程&#xff0c;首先客户端通过TCP三次握手与Server层的连接器建立连接&#xff08;短连接与长链接&#xff09;&#xff0c;缓存权限。然后去查询缓存&#xff08;8.0后移除&…

联想服务器双品牌的思考:融合化、场景化、订阅化、绿色化,打造全栈新算力基础设施

联想集团执行副总裁兼中国区总裁刘军&#xff1a;智能化转型是中国企业未来十年穿越经济周期的利器&#xff0c;智能化生产力水平决定了企业发展的速度与高度。 联想创新性提出融合化、场景化、订阅化及绿色化的“四维算力”&#xff0c;致力于成为中国领先的智能IT基础设施提供…

微服务--Feign学习

Feign远程调用&#xff1a; RestTemplate发起远程调用的代码&#xff1a; 存在下面的问题 代码可读性差&#xff0c;编程体验不统一参数复杂URL难以维护 Feign的介绍&#xff1a;Feign是一个声明式的http客户端&#xff0c;官方地址&#xff1a;https://github.com/OpenFeign/…

论文文献引用规范和标准(国标GBT7714)@endnote国标样式

文章目录论文文献引用规范和标准&#xff08;国标GBT7714&#xff09;国标GBT7714-2015endnote stylerefs简述国标GBT7714条目的组织格式Noteword中的文献交叉引用超链接文献引用示例endNote资源和基本使用endnote或其他文献引用工具下载word中的其他引文技巧知网国标格式引文引…

谈谈Java Optional的坑

开端&#xff1a; 大家好&#xff0c;我是老白。昨天朋友提出的java8后出来的自带的对象判定方式Optional.ofNullable(),后来查询了一些资料和自己试验了一些demo资料&#xff0c;在这里记录分享个大家 作用&#xff1a;判断对象是否为空&#xff0c;是则重新创建一个新对象&…

ABAP 搜索帮助带出多个字段描述 更新屏幕字段

文章目录需求解析1-DYNP_GET_STEPL2-F4IF_INT_TABLE_VALUE_REQUEST3-获取返回值4-把相应字段更新到内表5-DYNP_VALUES_UPDATE代码需求 如图,当我点击责任工序的搜说帮助时, 同时会把责任人员的描述带出来. 解析 1-DYNP_GET_STEPL 这个方法就是获取当前的循环步骤 2-F4IF_I…

浏览器中的 JavaScript 执行机制

思维导图 本文为反复学习极客时间-《浏览器的工作原理与实践》-浏览器中的 JavaScript 执行机制章节中的一些思考与记录。 一些重要概念 变量提升 所谓的变量提升&#xff0c;是指在 JavaScript 代码执行过程中&#xff0c;JavaScript 引擎把变量的声明部分和函数的声明部分…

你可能还不知道的 console.log 替代品

通过使用 javascript 对象的破坏能力&#xff0c;您可以这样做&#xff1a;const{ log } console; log("hi"); log("testing");你可以将log函数更改为您想要的任何其他名称&#xff0c;如下所示&#xff1a;const{log: myLog } console; myLog("hi&qu…

vue插槽 Slots

一、插槽是什么&#xff1f; 插槽就是子组件中的提供给父组件使用的一个占位符&#xff0c;用<slot></slot> 表示, 父组件可以在这个占位符中填充任何模板代码&#xff0c;如 HTML、组件等&#xff0c;填充的内容会替换子组件的<slot></slot>标签。 简…

OpenSergo Spring Cloud Alibaba 带来的服务治理能力

作者&#xff1a;十眠、牧思 Spring Cloud 应用为何需要服务治理 随着微服务技术的发展&#xff0c;微服务(MicroServices) 的概念早已深入人心&#xff0c;越来越多的公司开始使用微服务架构来开发业务应用。 如果采用得当&#xff0c;微服务架构可以带来非常大的优势。微服…

IDEA与eclipse桌面配置基础(笔记)

在eclipse中配置jdk Window–>Preferences–>java–>installed JREs–>add–>Standard VM–>选择jdk安装路径就好了 设置字符集编码为utf-8&#xff0c;防止中文乱码 设置字符集编码为UTF-8&#xff1a;Window–>Preferences–>General–>Workspace…

第四次工业革命新十年:看跨越智能化鸿沟的联想范式

十年前&#xff0c;GE推出全球第一个工业互联网平台Predix&#xff1b;同年&#xff0c;在2013汉诺威工业博览会上&#xff0c;德国正式推出工业4.0概念。由此&#xff0c;全球开启了以工业4.0和工业互联网为核心的第四次工业革命浪潮&#xff0c;智能技术成为了第四次工业革命…

4N25光耦合器:简单的应用电路

4N25光耦合器&#xff1a;简单的应用电路 介绍 4N25是一款6引脚光电晶体管耦合器。本文根据其传动特性介绍了 4N25 的非线性和线性应用。 4N25概述 光电耦合器4N25的内部电路结构如图1所示。 图1.4N25内部电路结构 该芯片为双列直插式器件&#xff0c;外引线为6根&#xff0…

Dart语法学习-基础-类

Classes Using constructors 使用构造函数创建对象。 构造函数名称可以是 ClassName 或 ClassName.identifier。 例如&#xff0c;以下代码使用 Point() 和 Point.fromJson() 构造函数创建 Point 对象&#xff1a; class Point {var x;var y;Point(int this.x, int this.y);…