
多线程
jym12138
积极向上的小码农
展开
专栏收录文章
- 默认排序
- 最新发布
- 最早发布
- 最多阅读
- 最少阅读
-
并发编程---并发安全
类的线程安全定义 如果多线程下使用这个类,不管多线程如何使用和调度这个类,这个类总是表示出正确的行为,这个类就是线程安全的。 类的线程安全表现为: 操作的原子性 内存的可见性 不做正确的同步,在多个线程之间共享状态的时候,就会出现线程不安全。 如何能做到类的线程安全 栈封闭 所有的变量都是在方法内部声明的,这些变量都处于栈封闭状态。 无状态 没有任何成员变量的类,就叫无状态的类。 让类不可变 让状态不可变,两种方式: 加final关键字,对于一个类,所有的成员变量应该是私有的,同样的只要有可能,所有的原创 2020-08-25 13:30:58 · 342 阅读 · 0 评论 -
并发编程 --- 线程池
为什么要用线程池 降低资源的消耗。降低线程创建和销毁的资源消耗; 提高响应速度:线程的创建时间为T1,执行时间T2,销毁时间T3,免去T1和T3的时间 提高线程的可管理性。 线程池的创建 ThreadPoolExecutor,jdk所有线程池实现的父类。 各个参数的含义 corePoolSize :线程池中核心线程数,< corePoolSize ,就会创建新线程,= corePoolSize ,这个任务就会保存到BlockingQueue,如果调用prestartAllCoreThreads()原创 2020-07-15 19:06:59 · 384 阅读 · 0 评论 -
并发编程--- 并发容器(除ConcurrentHashMap )与阻塞队列
ConcurrentSkipListMap 和 ConcurrentSkipListSet 相当于 TreeMap 和 TreeSet 有序的容器,这两种容器的并发版本 SkipList(跳表): 以空间换时间,在原链表的基础上形成多层索引,但是某个节点在插入时,是否成为索引,随机决定,所以跳表又称为概率数据结构。 ConcurrentLinkedQueue LinkedList的并发版本。 无界非阻塞队列,底层是个链表,遵循先进先出原则。add,offer将元素插入到尾部,peek(拿头部的数据,但是不原创 2020-07-13 10:59:47 · 462 阅读 · 0 评论 -
并发编程--- ConcurrentHashMap 简单梳理
ConcurrentHashMap 为什么多线程环境下使用 ConcurrentHashMap : Hashmap :在多线程环境下,会导致HashMap的Entry链表形成环形数据结构,一旦形成环形的数据结构,Entry 链表 next 节点永远不为空,就会产生死循环获取 Entry。 HashTable : HashTable使用synchronized来保证线程安全,但在线程竞争激烈的情况下HashTable的效率非常低下。因为当一个线程访问HashTable的同步方法,其他线程也访问HashTabl原创 2020-07-13 10:36:21 · 831 阅读 · 0 评论 -
并发编程---浅析AQS
LockSupport park开头的方法:负责阻塞线程。 unpark方法:负责唤醒线程。 AbstractQueuedSynchronizer (AQS)分析: AQS中使用的设计模式:模板模式。 模板方法: 独占式获取: accquire acquireInterruptibly tryAcquireNanos 共享式获取 acquireShared acquireSharedInterruptibly tryAcquireSharedNanos 独占式释放锁 release 共享式释放锁原创 2020-07-03 11:07:19 · 2758 阅读 · 0 评论 -
并发编程---显示锁Lock
lock (显示锁) Lock是一个接口,提供了无条件的、可轮询的、定时的、可中断的锁获取操作,所有的加锁和解锁操作方法都是显示的,因而称为显示锁。 Lock接口和核心方法 lock,unlock,trylock Lock 使用的标准范式 package com.jym.concurrent.lock; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; public class原创 2020-07-03 10:52:17 · 286 阅读 · 0 评论 -
并发编程---- CAS与原子操作类
CAS 什么是CAS: Compare and Swap,即比较再交换。 CAS原理: 三个运算符:一个内存地址V,一个期望的值A,一个新值B。 基本思路:如果地址V上的值和期望的值A相等,就给地址V赋给新值B,如果不是,不做任何操作。 在多线程的环境下,对一个变量进行写操作,可以在循环里不断的进行CAS操作。 CAS产生的问题: ABA 问题: 并发1(上):获取出数据的初始值是A,后续计划实施CAS乐观锁,期望数据仍是A的时候,修改才能成功。 并发2:将数据修改成B。 并发3:将数据修改回A。 并原创 2020-07-03 09:55:15 · 254 阅读 · 0 评论 -
并发编程----Callable、Future和FutureTask
FutureTask 常用的 Api get():获取任务的返回结果,如果任务没执行完,会一直阻塞等待任务执行完毕。 isDone :结束,正常还是异常结束,或者自己取消,返回true; isCancelled:任务完成前被取消,返回true; cancel(boolean): 任务还没开始,返回false 任务已经启动,cancel(true),中断正在运行的任务,中断成功,返回true,cancel(false),不会去中断已经运行的任务。 任务已经结束,返回false。 代码实例: packag.原创 2020-06-23 15:31:59 · 260 阅读 · 0 评论 -
并发编程工具类 ---- CountDownLatch 与 CyclicBarrier 的用法与区别
CountDownLatch 作用: 是一组线程等待其他的线程完成工作以后在执行,加强版join。await用来等待,countDown负责计数器的减 1. 代码演示: package com.jym.thread; import java.util.concurrent.CountDownLatch; /** * @program: jym-concurrent * @description: 定义一个阈值为6的 CountDownLatch ,启动5个线程来 countdown,来开启业务线程的原创 2020-06-12 11:18:37 · 289 阅读 · 0 评论 -
并发编程---- Fork-Join框架
什么是分而治之? 规模为N的问题,N<阈值,直接解决,N>阈值,将N分解为K个小规模子问题,子问题互相对立,与原问题形式相同,将子问题的解合并得到原问题的解。 工作密取 当有线程子任务结束后,该线程就会从子任务的队列中密取最后的任务继续执行。 Fork/Join使用的标准范式 Fork/Join的同步用法(invoke) 需求:计算一个数组中所有元素的和。 package com.jym.thread.forkJoin; import java.util.Random; /** * @原创 2020-06-12 11:12:50 · 259 阅读 · 1 评论 -
并发编程---- 线程的优先级,协作,通信
线程的生命周期: yield 方法 :将线程从运行转到可运行状态。 直接调用run方法,相当于 main 线程的调用 调用 start 方法,相当于新建的那个线程调用了 run 方法。 线程的优先级: 线程的优先级为 1-10 ,如果不设置 默认为5 通过setPriority 方法来设置。1为最高优先级。 守护线程 和主线程共死的,主线程退出了 守护线程也会退出。所以守护线程中的finally代码块 不能保证一定执行。 线程间的共享 synchronized 内置锁: 保证只能有一个线程 处于同步块原创 2020-06-12 11:02:58 · 232 阅读 · 0 评论 -
并发编程---- 如何让线程安全的停止工作
常用让线程停止工作的 API stop() :终结一个线程的时候,无法保证资源释放。 suspend() :线程不会释放资源。其他线程拿不到资源,容易出现死锁问题。 interrupt() :中断一个线程。并不是强行关闭这个线程,打个招呼。中断标志位 置为 true isInterrupted() :判断当前线程是否处于中断状态 判读中断标志位 是否为 true static 的 isInterrupted()方法 :判断当前线程是否处于中断状态,会把中断标志位 改为 false 继承Thread 使用原创 2020-06-12 10:43:22 · 285 阅读 · 0 评论 -
并发编程----基本概念以及启动线程的三种方式
基本概念 1.CPU的核心数 和线程数的关系 核心数 :线程数 = 1:1 ; 超线程技术 1:2 2.CPU 时间片轮转机制 RR调度:给每一个进程分配一个时间段,这个时间段被称为该进程的时间片,进程允许运行的时间。过了这段时间片,会上下文切换。 3.什么是进程和线程 进程:程序运行资源分配的最小单位,一个进程内部可以有多个线程,多个线程会共享这个进程的资源,进程与进程之间相互独立 线程:cpu 调度的最小单位,本身不能独立运行,要依赖于进程。 4.澄清并行和并发 并行:同一时间段,处理事情的能力 并发原创 2020-06-12 10:33:31 · 190 阅读 · 0 评论 -
线程同步类:CyclicBarrier
CyclicBarrier:栅栏 构造方法: // 一起执行的线程数 public CyclicBarrier(int parties) // 一起执行的线程数,barrierAction优先开始执行的线程 public CyclicBarrier(int parties, Runnable barrierAction) 主要方法: await方法:让线程进入barrier状态,当进入barri...原创 2020-01-31 10:25:54 · 10268 阅读 · 0 评论 -
线程同步类:Semaphore
Semaphore: 控制访问线程资源数量类 构造方法: // permits为访问线程的数量 Semaphore semaphore = new Semaphore(int permits); 主要方法: semaphore.acquire() : 获取运行许可,并阻塞其他线程 semaphore.release() : 释放许可,让其他线程运行 使用场景: 控制该段代码,每次最多两个线程执行...原创 2020-01-31 09:50:47 · 10191 阅读 · 0 评论 -
线程同步类:CountDownLatch
CountDownLatch:门阀 构造方法: // count为门阀数,必须大于0,否则抛出异常 CountDownLatch countDownLatch = new CountDownLatch(int count); 举个例子:在运动会上短跑比赛的时候,有8个运动员和一个裁判,把裁判当做主线程,只有等8个运动员全部完成比赛,有成绩之后,才能做出统计,完成后面的操作(调用await方法),...原创 2020-01-31 09:38:39 · 10203 阅读 · 0 评论 -
面试题:三个线程ABC,将名字按顺序输出到控制台,如ABCABC.....
题目:有三个线程,名字为A,B,C,现在需要将它们的名字有序的打印在控制台上,顺序为ABCABC… 思路: 因为要控制某个线程的执行顺序,所以采用lock+condition+ewait+signalAll的方式 执行线程方法的类: class ABC { private int num = 1; Lock lock = new ReentrantLock(); // 每...原创 2020-01-29 16:16:19 · 11934 阅读 · 0 评论 -
面试题:简单的实现一个生产者与消费者
思路:我们需要一个生产商品的线程类,以及一个消费商品的线程类,还有一个工具类,是编写生产以及消费的方法,供线程去调用 工具类: /** * 工具类,生产与消费的方法 */ class Cherk{ // 商品库存 private int product = 0; // 10个商品为最大库存量,为此生产出一个商品 public synchronized void produ...原创 2020-01-29 16:01:51 · 12303 阅读 · 1 评论 -
线程的执行状态以及通信方式
线程的五种状态: 先上图: 1.新建(new): 新建了一个线程对象. 2.可运行(runnable): 线程对象创建后,其他线程(比如mian线程)调用了该对象的start方法,该状态的线程位于可运行线程池中,等待被线程调度选中,获取cpu的使用权 3运行(running): 可运行状态的线程获得了cpu时间片,执行程序代码 4.阻塞(blocked): 阻塞状态是指线程因为某种原因放弃了cp...原创 2020-01-29 15:38:32 · 11049 阅读 · 0 评论 -
CAS机制以及简单实现
CAS: CAS是英文单词Compare And Swap的缩写,翻译过来就是比较并替换 CAS的三个基本参数: 内存值,预估值与更新值 具体流程为: 线程2在读取变量i时,读取的预估值为0,但是此时线程1把i改成了1,主内存的i值为1.所以内存值与预估值不一样,需要重新读取在进行操作。 当内存值与预估值不一样的时候,就会取消操作,重新读取,确保变量一致 下面我们简单用代码实现一下CAS: pa...原创 2020-01-28 22:06:33 · 11300 阅读 · 0 评论 -
多线程的风险
在使用多线程的时候,如果使用不当,代码执行的结果就会跟意想的有很大的差别 先看下面的一段代码: 线程类: class JymThread1 implements Runnable{ private int number; public void run() { try { Thread.sleep(200); } catch...原创 2020-01-28 21:48:44 · 10989 阅读 · 0 评论 -
volatile关键字的作用
volatile: 最轻量级的同步机制 一个变量被volatile修饰后,就有了两个特性: 1.可见性: 保证变量所有线程可见,当这个变量进行修改时,所有线程都会得知,普通的变量会有一个来回copy的过程,而volatile会马上看到 2.禁止指令重新排序优化: 正常代码是从上往下执行的,但是jdk有时候会对代码进行优化,不一定是从上往下执行的,但是执行的结果是一样的 但是volatile会禁止j...原创 2020-01-28 12:57:50 · 11747 阅读 · 0 评论 -
线程的运行模型
主内存: 所有线程之间共享,所有变量都存放在主内存中。 线程与与线程无法通信 线程与与线程无法通信,只能通过主内存,当线程想改变主内存中的值时,会将主内存的值copy一份,放入工作内存中,然后把值改变替换,替换后,将值返回到主内存中,然后将主内存的值给覆盖,这样就完成了值的修改 具体通信流程: 通信步骤: 1.read(读取):将主内存中的变量值读取 2.load(加载):将读取的值加载到线程的...原创 2020-01-28 12:36:11 · 11287 阅读 · 0 评论 -
ForkJoinPool的使用
ForkJoinPool 充分利用CPU,多核CPU的优势,会将一个大的任务拆分成多个小的任务,并通过线程来执行每个小任务,再把多个小任务的结果合并成总的计算结果。 窃取模式: 拆分完小任务后,会随机分配给线程队列,四个CPU有四个队列,会出现一个队列有多个任务或者没有任务的情况,如果有的小任务比较耗时,其他队列中没有任务,会从有任务的队列中窃取任务进行。 好处: 对比一般线程池的好处: 如果一...原创 2020-01-28 12:12:02 · 11985 阅读 · 0 评论 -
创建线程的四种方式(二)
线程: CPU调度和分配的最小单位,基本不浪费系统资源,只占用少数程序必备的资源。 上篇文章说了前三种方式,下面来说最后一种: 线程池方式创建线程: 为什么要用线程池: 如果并发量很多,并且每个线程都是执行时间很短就结束了,频繁的创建和销毁线程是非常消耗时间的。所以出现了线程池. 线程池: 执行完任务后,并不销毁,而是重新回到线程池内,等待下个任务,跟数据库连接池一样。 线程池使用规则: 1.工厂...原创 2020-01-27 21:58:10 · 11873 阅读 · 0 评论 -
创建线程的四种方式(一)
线程: CPU调度和分配的基本单位,基本不用系统资源,只拥有一点在运行中必不可少的资源 创建线程的四种方式 1. 实现Runnable接口,重写run方法 具体做法: class RunnableDemo implements Runnable{ public void run() { for (int i = 0, j=10;i<j;i++){ ...原创 2020-01-27 21:44:47 · 12016 阅读 · 0 评论 -
多线程的好处与弊端
在创建线程之前先说明一下基本概念: 串行与并行: 串行(同步):模仿人类做事,做完一件事之后做下一件事(比如穿衣服上厕所) 并行(异步): 做一件事的时候,不用等上件事情做完,就做下一件事情(比如吃饭的时候同时还可以看视频玩手机) 线程与进程: 线程:CPU调度和分配的基本单位,基本不用系统资源,只拥有一点在运行时必不可少的资源(大约占用1M内存) 进程:应用程序的一次执行过程 线程与进程之间...原创 2020-01-27 21:36:32 · 15126 阅读 · 0 评论