JUC系列(一) 多线程基础复习

高并发JUC详解 多线程进阶之高并发编程 阅读详情

什么是JUC

问:如何学习JUC?

答: 源码 + Java帮助文档 面试高频,

juc 其实就是 Java.util 包下的线程分类的工具

image-20220301194131214

以往学习的线程只是:

			我们使用的普通的线程代码 Thread,==Runnable== 等其实回顾JavaSE的线程知识我们可以发现, 

其实我们学习线程基础的时候,也是有用到concurrent包下的东西

比如 Runnable 和 Callable ,Callable 就是我们concurrent 包下的

还有就是 Lock

image-20220301194541263

线程与进程

线程、进程、如何来解释

进程 : 一个程序 如 QQ.exe Music.exe 程序的集合

一个进程可以包含多个线程,至少包含一个线程

Java 默认是开启两个线程 main GC

线程: 开了一个进程 比如: typora 写字,自动保存(线程负责的)

对于Java 而言创建线程我们学习到的方法有三种 : Thread , Runnable , Callable

PS :Java本身是无法开启线程的!!!

    public synchronized void start() {
        /**
         * This method is not invoked for the main method thread or "system"
         * group threads created/set up by the VM. Any new functionality added
         * to this method in the future may have to also be added to the VM.
         *
         * A zero status value corresponds to state "NEW".
         */
        if (threadStatus != 0)
            throw new IllegalThreadStateException();

        /* Notify the group that this thread is about to be started
         * so that it can be added to the group's list of threads
         * and the group's unstarted count can be decremented. */
        group.add(this);

        boolean started = false;
        try {
            start0();
            started = true;
        } finally {
            try {
                if (!started) {
                    group.threadStartFailed(this);
                }
            } catch (Throwable ignore) {
                /* do nothing. If start0 threw a Throwable then
                  it will be passed up the call stack */
            }
        }
    }

	// 本地方法 调用底层的 C++ Java本身不能直接操作硬件
    private native void start0();

并发,并行

我们要学习并发编程,首先要了解 : 并发和并行是什么

并发(多线程操作同一资源)

  • CPU一核,模拟出来多条线程,天下武功,唯快不破,快速交替。

并行(多个程序一起走)

  • CPU 多核,多个线程同时执行;如果需要提高性能 : 线程池

查看一下自己的cpu核数

image-20220301201453940

并发编程的本质:充分利用CPU的资源

所有的公司都很看重,就是效率,比如裁员:一个厉害的可以大于两个不再那么厉害的甚至更多

比如: 做事情的速度 高手:1s,一般人: 10s 肯定是 1s 的更加的之前也更加的有效率;

做到人员(减少),但是技术力却提高了

线程有几个状态

通过Thread 源码里的枚举类:State 中的属性可以看出来

线程有六个状态

    public e
num State {
        //新的线程
        NEW,
        //运行中
        RUNNABLE,
        // 阻塞
        BLOCKED,
        //等待,一直等
        WAITING,
        //等待一段时间就不等了
        TIMED_WAITING,
        // 终止线程
        TERMINATED;
    }

wait/sleep的区别

1、他们来自不同的类

wait => object

sleep => Thread

2、关于锁的释放

wait会释放锁,sleep不会释放锁

抽象理解 : sleep 睡着了没办法释放, wait 是等待,有人需要的释放

wait必须在同步代码块中使用,得有需要等的人

sleep可以在任何地方使用

3、是否需要捕获异常

wait 不需要捕获异常

sleep 需要捕获异常

Lock锁

传统 Synchronized

传统火车票案例

/**
 * @projectName: JUC
 * @package: Thread
 * @className: SaleTicketDemo
 * @author: 冷环渊 doomwatcher
 * @description: TODO
 * @date: 2022/3/1 20:28
 * @version: 1.0
 */
public class SaleTicketDemo {
    /**
     * 真正的多线程开发 公司中的需要降低耦合性
     * 线程就是一个单独的资源类,没有任何附属的操作
     * 1、 属性。方法
     * */
    public static void main(String[] args) {
        //并发: 多线程操作同一个资源类,把资源丢入线程
        Ticket ticket = new Ticket();
        new Thread(() -> {
            for (int i = 0; i < 40; i++) {
                ticket.sale();
            }
        }, "A").start();
        new Thread(() -> {
            for (int i = 0; i < 40; i++) {
                ticket.sale();
            }
        }, "B").start();
        new Thread(() -> {
            for (int i = 0; i < 40; i++) {
                ticket.sale();
            }
        }, "C").start();
    }
}

//资源类 OOP
class Ticket {
    //属性 方法
    private int number = 50;

    //    买票的方式
    public synchronized void sale() {
        if (number > 0) {
            System.out.println(Thread.currentThread().getName() + "卖出了" + (number--) + "票,剩余" + number);
        }
    }
}

Lock接口

image-20220301204107904

常用的一些实现类

image-20220301204151242

image-20220301204430613

公平锁 : 十分公平,可以先来后到 比如 前一个线程要执行30s 后面的 需要3s 后者必须等待前者执行完

非公平锁 : 十分不公平,可以根据条件来插队

如何用Lock来编写火车票Demo

  1. new ReentrantLock();
  2. Lock.lock(); 解锁
  3. finally => lock.unlock(); 解锁

Synchronized和Lock区别

  1. Synchronized 内置的java关键字,Lock是一个java类
  2. Synchronized 无法获取锁的状态 Lock 可以判断是否获取到锁
  3. Synchronized 会自动释放锁, Lock 必须手动解锁,如果不释放锁 就会死锁
  4. Synchronized 线程1(获得锁,阻塞),线程2(等待,死等),Lock锁不一定会等待
  5. Synchronized 可重入锁,不可以中断,非公平,Lock 可重入锁,可以判断锁,手动调整
  6. Synchronized 适合锁少量代码同步问题,Lock 适合锁大量的同步代码

锁是什么,如何判断锁的是谁

生产者和消费者问题

生产者和消费者问题:Synchronized 版

面试高频 : 单例模式,排序算法,生产者和消费者 死锁

package ProduceAndconsum;

/**
 * @projectName: JUC
 * @package: ProduceAndconsum
 * @className: A
 * @author: 冷环渊 doomwatcher
 * @description: TODO
 * @date: 2022/3/1 21:08
 * @version: 1.0
 */
public class A {
    public static void main(String[] args) {
        Data data = new Data();
        new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                try {
                    data.increment();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }, "A").start();
        new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                try {
                    data.decrement();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }, "B").start();
    }
}

//数字 资源类
// 1、 判断等待,通知
class Data {
    private int number = 0;

    //    +1
    public synchronized void increment() throws InterruptedException {
        if (number != 0) {
            //    等待
            this.wait();
        }
        number++;
        System.out.println(Thread.currentThread().getName() + "=>" + number);
        //    通知其他线程 +1 完毕了
        this.notifyAll();
    }

    //    -1
    public synchronized void decrement() throws InterruptedException {
        if (number == 0) {
            //    等待
            this.wait();
        }
        number--;
        System.out.println(Thread.currentThread().getName() + "=>" + number);
        //    通知其他线程 -1 完毕了
        this.notifyAll();
    }
}

但是,写出来这个简单的模型 面试官还是会挑的出毛病来,问题出在那?

问题,现在我们是两个线程 ,我们加到四个线程 A,B,C,D 现在还是安全的吗?答案是肯定的不是

虚假唤醒问题:我们增加到四个线程输出的时候就会发现一些问题来,输出不再是0101了

image-20220301212425229

image-20220301212149214

这里如何解决呢? 将 if 换成 while循环

修改之后根据官方文档的解释之后,将if改编成while

image-20220301212605922

输出就又回到了正常

package ProduceAndconsum;

/**
 * @projectName: JUC
 * @package: ProduceAndconsum
 * @className: A
 * @author: 冷环渊 doomwatcher
 * @description: TODO
 * @date: 2022/3/1 21:08
 * @version: 1.0
 */
public class A {
    public static void main(String[] args) {
        Data data = new Data();
        new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                try {
                    data.increment();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }, "A").start();
        new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                try {
                    data.decrement();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }, "B").start();
        new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                try {
                    data.increment();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }, "C").start();
        new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                try {
                    data.decrement();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }, "D").start();
    }
}

//数字 资源类
// 1、 判断等待,通知
class Data {
    private int number = 0;

    //    +1
    public synchronized void increment() throws InterruptedException {
        while (number != 0) {
            //    等待
            this.wait();
        }
        number++;
        System.out.println(Thread.currentThread().getName() + "=>" + number);
        //    通知其他线程 +1 完毕了
        this.notifyAll();
    }

    //    -1
    public synchronized void decrement() throws InterruptedException {
        while (number == 0) {
            //    等待
            this.wait();
        }
        number--;
        System.out.println(Thread.currentThread().getName() + "=>" + number);
        //    通知其他线程 -1 完毕了
        this.notifyAll();
    }
}

生产者和消费者问题: JUC版

在新的学习中 synchronized 有 Lock 替换

那么 wait 和 notify谁来替换呢?

image-20220301212829262

通过 Lock来找到 Condition

image-20220301213020385

image-20220301213059259

package ProduceAndconsum;

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

/**
 * @projectName: JUC
 * @package: ProduceAndconsum
 * @className: B
 * @author: 冷环渊 doomwatcher
 * @description: TODO
 * @date: 2022/3/1 21:31
 * @version: 1.0
 */


public class B {
    public static void main(String[] args) {
        Data2 data = new Data2();
        new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                try {
                    data.increment();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }, "A").start();
        new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                try {
                    data.decrement();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }, "B").start();
        new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                try {
                    data.increment();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }, "C").start();
        new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                try {
                    data.decrement();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }, "D").start();
    }
}

//数字 资源类
// 1、 判断等待,通知
class Data2 {
    private int number = 0;
    Lock lock = new ReentrantLock();
    Condition condition = lock.newCondition();
    //等待
    //    condition.await();
    //唤醒全部
    //    condition.signalAll();

    //    +1
    public void increment() throws InterruptedException {
        lock.lock();
        try {
            while (number != 0) {
                //    等待
                condition.await();
            }
            number++;
            System.out.println(Thread.currentThread().getName() + "=>" + number);
            //    通知其他线程 +1 完毕了
            condition.signalAll();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    //    -1
    public void decrement() throws InterruptedException {
        lock.lock();
        try {
            while (number == 0) {
                //    等待
                condition.await();
            }
            number--;
            System.out.println(Thread.currentThread().getName() + "=>" + number);
            //    通知其他线程 -1 完毕了
            condition.signalAll();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }
}
package ProduceAndconsum;

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

/**
 * @projectName: JUC
 * @package: ProduceAndconsum
 * @className: B
 * @author: 冷环渊 doomwatcher
 * @description: TODO
 * @date: 2022/3/1 21:31
 * @version: 1.0
 */


public class B {
    public static void main(String[] args) {
        Data2 data = new Data2();
        new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                try {
                    data.increment();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }, "A").start();
        new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                try {
                    data.decrement();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }, "B").start();
        new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                try {
                    data.increment();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }, "C").start();
        new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                try {
                    data.decrement();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }, "D").start();
    }
}

//数字 资源类
// 1、 判断等待,通知
class Data2 {
    private int number = 0;
    Lock lock = new ReentrantLock();
    Condition condition = lock.newCondition();
    //等待
    //    condition.await();
    //唤醒全部
    //    condition.signalAll();

    //    +1
    public void increment() throws InterruptedException {
        lock.lock();
        try {
            while (number != 0) {
                //    等待
                condition.await();
            }
            number++;
            System.out.println(Thread.currentThread().getName() + "=>" + number);
            //    通知其他线程 +1 完毕了
            condition.signalAll();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    //    -1
    public void decrement() throws InterruptedException {
        lock.lock();
        try {
            while (number == 0) {
                //    等待
                condition.await();
            }
            number--;
            System.out.println(Thread.currentThread().getName() + "=>" + number);
            //    通知其他线程 -1 完毕了
            condition.signalAll();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }
}

任何的一个新技术,都不可能是单纯的去替代老的技术,一定有优化和补充

Condition

image-20220301214146773

我们更换完代码之后,可以正常输出但是还是混乱的,我们想要达到 A->B->C->D 这样输出,这个时候就引出了新的知识点

Conddition精准唤醒

package ProduceAndconsum;

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

/**
 * @projectName: JUC
 * @package: ProduceAndconsum
 * @className: B
 * @author: 冷环渊 doomwatcher
 * @description: TODO
 * @date: 2022/3/1 21:31
 * @version: 1.0
 */


public class C {
    public static void main(String[] args) {
        Data3 data = new Data3();
        new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                data.printA();
            }
        }, "A").start();
        new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                data.printB();
            }
        }, "B").start();
        new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                data.printC();
            }
        }, "C").start();
    }
}

//数字 资源类
// 1、 判断等待,通知
class Data3 {
    private int number = 1;
    Lock lock = new ReentrantLock();
    Condition condition = lock.newCondition();
    Condition condition1 = lock.newCondition();
    Condition condition2 = lock.newCondition();

    public void printA() {
        lock.lock();
        try {
            //    业务,判断 执行 通知
            while (number != 1) {
                //等待
                condition.await();
            }
            System.out.println(Thread.currentThread().getName() + "=>AAA");
            number = 2;
            condition1.signal();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    public void printB() {
        lock.lock();
        try {
            //    业务,判断 执行 通知
            while (number != 2) {
                //等待
                condition1.await();
            }
            System.out.println(Thread.currentThread().getName() + "=>BBB");
            number = 3;
            condition2.signal();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    public void printC() {
        lock.lock();
        try {
            //    业务,判断 执行 通知
            while (number != 3) {
                //等待
                condition2.await();
            }
            System.out.println(Thread.currentThread().getName() + "=>BBB");
            number = 1;
            condition.signal();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }
}

输出的结果就达到我们的预期了

image-20220301215538935

JUC高并发编程从入门到精通(全) 目录前言 前言 在了解这部分内容的时候 先要了解java的一些基础内容 java零基础从入门到精通(全) javaSE从入门到精通(全) 所谓JUC是java.util .concurrent 工具包的简称这是一个处理线程的工具包可以实现多线程高并发的内容 了解该部分内容先了解线程与进程的相关概念 【操作系统】线程与进程的深入剖析(全) java之Thread类详细分析(全) 以及涉及到的lambda表达式函数的概念 java中lambda表达式 ...... 阅读详情

相关推荐

FR4板材实战:用ADS 2023快速设计微带线低通滤波器(附Line-Cal计算技巧)

本文详细介绍了使用ADS 2023在FR4板材上设计1-3GHz微带线低通滤波器的工程技巧。通过Line-Cal工具快速计算微带线参数,解决FR4板材的介质损耗和阻抗匹配问题,提供从集总参数转换到分布参数的实用方法,并分享版图设计与实测验证的关键要点,帮助工程师高效完成射频滤波器设计。

omega的博客 713

JUC并发编程

需要有一定的多线程基础,需要的小伙伴可以回到这个帖子来复习Java多线程 何为JUC? java.util.concurrent包 回顾线程和进程的区别 进程:一个程序,QQ.exe Music.exe 程序的集合; 一个进程往往可以包含多个线程,至少包含一个! Java默认有几个线程? 2 个 mian、GC 线程:开了一个进程 Typora,写字,自动保存(线程负责的) 对于Java而言:Thread、Runnable、Callable Java 真的可以开启线程吗? 开不了,因为底层调用还是jvm,

风吟Pro的博客 808

VisDrone2019数据集实战:从下载到YOLO格式转换的完整指南

本文提供了一份完整的VisDrone2019数据集实战指南,详细介绍了从数据集下载、理解其独特的标注格式,到转换为YOLO模型可直接训练格式的全过程。通过清晰的代码示例和步骤讲解,帮助读者掌握处理复杂无人机视觉数据集的核心技能,为基于YOLO的目标检测模型训练做好准备。

weixin_29165725的博客 384

JUC复习大总结

1.什么是虚假唤醒?(某个线程不应该被唤醒) 比如线程A和B同时陷入阻塞,线程C执行notifyAll(),线程A、B都被唤醒,但线程A唤醒执行后的结果应该导致B依旧阻塞,但B没有循环判断,导致也被唤醒!!下面有图解 以生产者-消费者模型举例。。 class Goods{ public int number=0; //制作方法 public synchronized void made() throws InterruptedException { //判断

放下键盘 291

机器人强化学习入门学习笔记

如果你追求高精度动力学仿真、用于强化学习或机器人研究,MuJoCo 是一个非常优秀的选择。如果需要快速实验、使用真实机器人模型,PyBullet 或 Gazebo可能更合适;如果你追求大规模并行训练,Isaac Gym 或 BraX会更高效。legged gym底层是​编辑isaacgym,基于gpu训练可以多环境并行训练,收敛到一个稳定行走的策略快。本视频MuJoCo基于cpu训练很慢。

xiaomu_347的博客 1469

用Python实现古诗词填字游戏(三)

古诗词做填字游戏的第三部分代码,也是最核心的部分。实现对诗文和关键字的选定,并确定文字的输出位置。

PosPro的专栏 6117

温故而知新-JUC篇【面试复习】

温故而知新-JUC篇【面试复习】

小心星的博客 1087

一文看懂分布式存储架构

目录一、集中存储结构二、分布式存储1 、分布式存储的兴起2 、分布式存储的重要性3 、分布式存储的种类和比较三、分布式理论浅析1 、一致性和可用性2 、数据分布3 、复制4 、分布式协议5、跨机房部署四、分布式文件系统1、 Google 文件系统( GFS )2、 Taobao 文件系统( TFS )3、 Fackbook Haystack 文件系统4、 CDN 内容分发网络五、分布式键值系统1、 Amazon Dynamo2、 Taobao Tiar3、 ETCD4 、产品选型比较( Etcd , Zoo

weixin_70730532的博客 2万+

JUC基础知识(个人总结)

    声明: 1. 本文为我的个人复习总结, 并非那种从零基础开始普及知识 内容详细全面, 言辞官方的文章               2. 由于是个人总结, 所以用最精简的话语来写文章            

hellosrc的博客 9207

CUDA:实现使用cuSolverSP底层API实现Cholesky因式分解(附完整源码)

CUDA:实现使用cuSolverSP底层API实现Cholesky因式分解(附完整源码)

希望我的博客,能帮上你解决学习中工作中所遇到的问题 346

couldn‘t upgrade db schema: insert into ACT_GE_PROPERTY values (‘common.sche[已解决]

启动整合了flowable的项目,初始化时报错。flowable没有自动建表, 原因 测试数据库版本是MySQL5.7。经过查询和尝试,原因是:在这个数据库里面,已经有一个数据库里面有activiti的这些表了,它检索的时候全库检索查到它了,所以flowable不去建表了,但是我们指定的这个schema里卖弄还是空的,所以它报了找不到表。解决方法:mysql的链接上加上参数如下,让本schema成为默认的schema。...

JavaPub 6014

Java面试复习体系总结(2021版,持续更新)

Java面试复习体系总结(2021版) 一、Java基础 内容 Java基础(一):Java集合框架(超详细解析,看完面试不再怕) Java基础(二):迭代器(Iterator)(含使用方法详解) Java基础 (三):LinkedList(含使用方法详解) Java基础(四):ArrayList(含使用方法详解) Java基础(五):HashSet(使用方法详解) Java基础(六):HashMap(使用方法详解) Java基础(七):栈 Stack(使用方法详解)

Viper的程序员修炼手册 11万+

Vue3 - 超详细“纯前端“将文件上传到阿里云OSS对象存储,最新阿里云前端直传音频、视频、图片、文件、office文档等任意文件,vue3单个或批量从本地选择文件,秒传到阿里云oss无需后端接口!

vue3,阿里云oss存储,前端直传oss,上传图片/office文档/音视频/zip压缩包到阿里云oss,项目中上传文件到阿里云oss详细教程,如何将本地文件上传到阿里云OSS存储,纯前端实现阿里云OSS上传,纯前端直传至阿里OSS对象存储教程,如何解决上传文件到阿里云OSS本地环境调试出现跨域问题,直传阿里云oss跨域报错解决,前端直接上传文件到oss服务端,不经过后端直传,浏览器直接上传文件,阿里云oss上传sdk官方文档,阿里云错误,解决这个问题,上传很慢,一直签名失败,权限,不经过后端,纯前端直传

🏆 前端领域优质创作者 1万+

JUC复习

JUC学习 文章目录JUC学习什么是JUC并发与并行线程锁Synchronized:是自动解锁。Lock:需要手动解锁线程间的通信Synchronized锁的通信Lock锁的通信解决线程不安全问题1.解决ArrayList线程不安全的方法2.解决Hashset线程不安全问题3.解决HashMap线程不安全问题多线程锁公平锁和非公平锁死锁JUC强大的辅助类CountDownLatch:作用减少计数CyclicBarrier:循环栅栏Semaphore:信号灯ReentrantReadWriteLock(读写锁

qq_52999613的博客 1036

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

复习JUC的总结笔记

调用Thread的start方法会调用start0,start0会调用该Thread类的run方法。Thread类如果传入了Runnable,run方法里会调用Runnable的run方法,如果没有传入,则什么也不会做。也可以通过重写Thread的run方法,让start0调用重写的run方法。start 方法只是让线程进入就绪,里面代码不一定立刻运行(CPU 的时间片还没分给它)。每个线程对象的start方法只能调用一次,如果调用了多次会出现IllegalThreadStateException。

m0_73520938的博客 982

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

【JUC】复习指南

这组过程可以根据资源共享的情况,或接收或阻塞进程的访问,确保每次仅仅有一个进程使用共享资源,这样就实现对共享资源的统一管理,实现互斥。但是有了接收缓存队列后,生产者可以保持运行,也不必等待消费者必须把缓冲区的内容消费了,生产者可以生产到缓存队列满了再停等,减少了系统的停等时间。通过一个缓存队列,把生产者和消费者的直接制约关系破坏,打破同步,形成异步关系,可以有效提高CPU的利用率,减少空等时间,提高了系统吞吐量。我们可以看到,JVM中的管程是线程粒度的,毕竟,一个JVM只对应一个工作进程。

Alex_cf的博客 306

Java基础进阶——多线程与JUC(上)

最近在准备面试,把知识点复习一遍,整理出的笔记记录下,里面会穿插代码和面试例题。 内容不是原创,是总结和收集,并在理解的基础上进行一些完善,如果侵权了请联系作者,若有错误也请各位指正。因为收集的时候忘记把来源记录下来了,所以就不po出处了,请见谅(这是个坏习惯,一定改)。 Java基础进阶——JUC多线程多线程 这是面试复习内容的第十三篇——多线程,主要是Java基础的内容,所有内容将分为几篇来写。 多线程 ...

尼尧Nier的博客 1102

Java基础进阶——多线程与JUC(下)

最近在准备面试,把知识点复习一遍,整理出的笔记记录下,里面会穿插代码和面试例题。 内容不是原创,是总结和收集,并在理解的基础上进行一些完善,如果侵权了请联系作者,若有错误也请各位指正。因为收集的时候忘记把来源记录下来了,所以就不po出处了,请见谅(这是个坏习惯,一定改)。 Java基础进阶——多线程与JUC(下)多线程与JUCReadWriteLock 读写锁锁降级ReentrantReadWriteLock 可重入读写锁Callable接口FutureList、Map、Set与线程安全List与线程安全

尼尧Nier的博客 398

万字长文扫盲JUC基础

JUC基础篇,锁

ljz66254的博客 1221

JUC精简版(快速复习使用)

JUC 什么是JUC? JUC是JDK提供的为解决线程问题的工具类,即java.util.concurrent的缩写。 1.线程与进程 首先我们需要明白的是进程 > 线程 (虽然并不严谨,但是可以这样认为) 用一句专业术语来描述他们之间的区别:进程是CPU资源分配的最小单位,线程是CPU调度的最小单位 知乎上一个匿名用户很好的比喻: 进程 一个进程就是CPU执行 ,是程序在执行过程当中CPU资源分配的最小单位,并且进程都有自己的地址空间,包含了运行态、就绪态、阻塞态、创建态、终止态五个状态。

TheAnnoyingDog的博客 1337

JUC的小复习

举个栗子--------某宝、某夕、某东,双十一双十二结束后,计算“数码区”,“汽车用品区”, “母婴品区”,它们各自的总流水账,以及它们三个总的流水账,那么比如数码区先获得cpu资源,先计算完后,得等待其他两个区计算结果后,才能计算“总”的流水账。1.CountDownLatch 闭锁------------------替换 join 方法--------“-”减法。非静态锁--------------class反射的对象,new几个就几把锁,但要考虑static修饰的情况。

m0_69912089的博客 798

【周阳-JUC入门】【01】多线程复习、JUC引入

JUC入门

Keep Reading Keep Writing Keep Thinking 529

尚硅谷JUC笔记

一、JUC介绍 1、面试常见问题类别 面向对象、高级语法(1、抽象类和接口有什么区别?2、Java中获得多线程有几种方法?) Java集合类(1、java.util.*中的ArrayList、Vector、LinkedList、TreeMap、HashSet、HashMap、ConcurrentHashMap、CopyOnWriteHashMap、Queue等?2、谈谈你对HashMap的理解,什么是Hash算法,什么是Hash碰撞?) Java多线程(1、Java中获得多线程的方法有几种?) Java

qq_42449963的博客 2467

JUC多线程详解,初学多线程的可以来看看,复习的也可适合来看(推荐)

程序是为完成特定任务,用某种语言编写的一组指令的集合,简单来说,就是我们写的代码Java 中的线程分为用户线程和守护线程程序中的所有的用户线程结束之后,不管守护线程处于什么状态,JVM 都会自动退出调用线程的实例方法 setDaemon() 来设置线程是否是守护线程setDaemon() 方法必须在线程的 start() 方法之前调用,在后面调用会报异常,并且不起效无论synchronized关键字加在方法上还是对象上,如果它作用的对象是非静态的,则它取得的锁是对象;

桂秋拾貳 1606

JUC高并发编程(一)——JUC基础知识

JUC高并发编程(一)——JUC基础知识

杨思默 5732

bilibili尚硅谷周阳老师JUC并发编程与源码分析课程笔记第一章——线程基础知识复习

如果用户线程全部结束意味着程序需要完成的业务操作已经结束了,守护线程随着JVM一同结束工作。

qq_46601365的博客 1610
上一篇: Spring拓展知识:后置处理器与事件监听器
下一篇: 线程池详解与异步任务编排使用案例
冷环渊
博客等级 码龄7年 1130粉丝 176原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

冷环渊

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值