IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> L6:Java并发1 -> 正文阅读

[Java知识库]L6:Java并发1

【目录】
1.多线程基础
2.Java 多线程*
3.线程安全*
4.线程池原理与应用*
5.6 课总结回顾与作业实践

一 基础

多线程产生的原因:摩尔定律失效 -> 多核心 + 分布式
多CPU核心意味着OS可以操作更多并行计算资源
OS是以线程作为基本的调度单元
在这里插入图片描述
进程与线程区别
在这里插入图片描述

二 Java多线程

创建线程的四种方式

守护线程

注意执行结果中线程的run方法体内代码并没有执行,因为将该线程设置为Deamon状态

public static void main(String[] args) {
        Runnable task = new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(5000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                Thread t = Thread.currentThread();
                System.out.println("当前线程:" + t.getName());
            }
        };
        Thread thread = new Thread(task);
        thread.setName("test-thread-1");
        thread.setDaemon(true);
        thread.start();
    }

线程状态

在这里插入图片描述
Thread 类属性和方法
在这里插入图片描述
在这里插入图片描述
注意:Thread.sleep 释放CPU | Object.wait 释放锁

线程状态状态改变操作

  1. Thread.sleep(long millis),一定是当前线程调用此方法,当前线程进入 TIMED_WAITING 状态,但不释放对象锁,millis 后线程自动苏醒进入就绪状态。作用:给其它线程执行机会的最佳方式;
  2. Thread.yield(),一定是当前线程调用此方法,当前线程放弃获取的 CPU 时间片,但不释放锁资源,由运行状态变为就绪状态,让 OS 再次选择线程。作用:让相同优先级的线程轮流执行,但并不保证一定会轮流执行。实际中无法保证yield() 达到让步目的,因为让步的线程还有可能被线程调度程序再次选中。Thread.yield() 不会导致阻塞。该方法与sleep() 类似,只是不能由用户指定暂停多长时间;
  3. t.join()/t.join(long millis),当前线程里调用其它线程 t 的 join 方法,当前线程进入WAITING/TIMED_WAITING 状态,当前线程不会释放已经持有的对象锁。线程t执行完毕或者 millis 时间到,当前线程进入就绪状态;
  4. obj.wait(),当前线程调用对象的 wait() 方法,当前线程释放对象锁,进入等待队列。依靠 notify()/notifyAll() 唤醒或者 wait(long timeout) timeout 时间到自动唤醒;
  5. obj.notify() 唤醒在此对象监视器上等待的单个线程,选择是任意性的。notifyAll() 唤醒在此对象监视器上等待的所有线程;

Thread中断和异常处理

  1. 线程内部自己处理异常,不溢出到外层;
  2. 如果线程被 Object.wait, Thread.join 和 Thread.sleep 三种方法之一阻塞,此时调用该线程的interrupt() 方法,那么该线程将抛出一个 InterruptedException 中断异常(该线程必须事先预备好处理此异常),从而提早地终结被阻塞状态。如果线程没有被阻塞,这时调用interrupt() 将不起作用,直到执行到 wait(),sleep(),join() 时,才马上会抛出InterruptedException;

线程状态转换图

在这里插入图片描述

三 线程安全

在这里插入图片描述

并发性质

ACID

指令重排机制(Happen-Before原则)

  1. 程序次序规则:一个线程内,按照代码先后顺序
  2. 锁定规则:一个 unLock 操作先行发生于后面对同一个锁的 lock 操作
  3. Volatile 变量规则:对一个变量的写操作先行发生于后面对这个变量的读操作
  4. 传递规则:如果操作 A 先行发生于操作 B,而操作 B 又先行发生于操作 C,则可以得出 A 先于 C
  5. 线程启动规则:Thread 对象的 start() 方法先行发生于此线程的每个一个动作
  6. 线程中断规则:对线程 interrupt() 方法的调用先行发生于被中断线程的代码检测到中断事件的发生
  7. 线程终结规则:线程中所有的操作都先行发生于线程的终止检测,我们可以通过 Thread.join() 方法结束、Thread.isAlive() 的返回值手段检测到线程已经终止执行
  8. 对象终结规则:一个对象的初始化完成先行发生于他的 finalize() 方法的开始

Synchronized的实现

  • 锁方法
  • 锁对象
  • 锁代码块

Volatile关键字

  1. 每次读取都强制从主内存刷数据
  2. 适用场景: 单个线程写;多个线程读
  3. 原则: 能不用就不用,不确定的时候也不用
  4. 替代方案: Atomic 原子操作类

四 线程池原理与应用

创建方式

  1. Excutor: 执行者 – 顶层接口(无返回参数 + 有返回参数)
  2. ExcutorService: 接口 API
  3. ThreadFactory: 线程工厂(构造函数参数含义)
  4. Executors: 工具类

ThreadFactory提交任务逻辑(源码)

  1. 判断 corePoolSize 【创建】
  2. 加入 workQueue
  3. 判断 maximumPoolSize 【创建】
  4. 执行拒绝策略处理器
    在这里插入图片描述

构造参数

缓冲队列分类

BlockingQueue 是双缓冲队列。BlockingQueue 内部使用两条队列,允许两个线程同时向队列一个存储,一个取出操作。在保证并发安全的同时,提高了队列的存取效率

  1. ArrayBlockingQueue:规定大小的 BlockingQueue,其构造必须指定大小。其所含的对象是 FIFO 顺序排序的。
  2. LinkedBlockingQueue:大小不固定的 BlockingQueue,若其构造时指定大小,生成的 BlockingQueue 有大小限制,不指定大小,其大小有 Integer.MAX_VALUE 来决定。其所含的对象是 FIFO 顺序排序的。
  3. PriorityBlockingQueue:类似于 LinkedBlockingQueue,但是其所含对象的排序不是 FIFO,而是依据对象的自然顺序或者构造函数的 Comparator 决定。
  4. SynchronizedQueue:特殊的 BlockingQueue,对其的操作必须是放和取交替完成

拒绝策略

  1. ThreadPoolExecutor.AbortPolicy:丢弃任务并抛出 RejectedExecutionException异常。
  2. ThreadPoolExecutor.DiscardPolicy:丢弃任务,但是不抛出异常。
  3. ThreadPoolExecutor.DiscardOldestPolicy:丢弃队列最前面的任务,然后重新提交被拒绝的任务
  4. ThreadPoolExecutor.CallerRunsPolicy:由调用线程(提交任务的线程)处理该任务

创建线程池方法

  1. newSingleThreadExecutor
    创建一个单线程的线程池。这个线程池只有一个线程在工作,也就是相当于单线程串行执行所有任务。如果这个唯一的线程因为异常结束,那么会有一个新的线程来替代它。此线程池保证所有任务的执行顺序按照任务的提交顺序执行。
  2. newFixedThreadPool
    内部使用LinkedQue,任务可能会一直堆积,造成OOM
    创建固定大小的线程池。每次提交一个任务就创建一个线程,直到线程达到线程池的最大大小。线程池的大小一旦达到最大值就会保持不变,如果某个线程因为执行异常而结束,那么线程池会补充一个新线程。
  3. newCachedThreadPool
    线程池大小不做限制,可能会OOM
    创建一个可缓存的线程池。如果线程池的大小超过了处理任务所需要的线程,那么就会回收部分空闲(60秒不执行任务)的线程,当任务数增加时,此线程池又可以智能的添加新线程来处理任务。此线程池不会对线程池大小做限制,线程池大小完全依赖于操作系统(或者说JVM)能够创建的最大线程大小。
  4. newScheduledThreadPool
    创建一个大小无限的线程池。此线程池支持定时以及周期性执行任务的需求

创建固定线程池经验
若核心数为N,

五 总结

  • 多线程基础
  • Java多线程
  • 线程安全
  • 线程池原理与应用
  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2021-08-31 15:19:02  更:2021-08-31 15:20:44 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 13:10:42-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码