CAS

Java集合框架

守給你的承諾、 提交于 2020-12-16 06:56:30
一、ArrayList与LinkedList的异同 1、都不保证线程安全的 2、底层数据结构不同。ArrayList是数组,LinkedList是双向链表。 3、插入和删除的时间复杂度与元素位置有关。ArrayList在尾部增删时时间复杂度为O(1),在非尾部操作时时间复杂度为O(n-i)。LinkedList增删操作时时间复杂度为O(1)。 4、ArrayList支持快速随机访问(使用get(int index)方法),LinkedList不支持快速随机访问 5、内存空间占用方面。ArrayList造成的空间浪费体现在list列表结尾会预留一定的空间,而LinkList空间花费体现在每个元素要比ArrayList多消耗直接前驱和后驱的空间。 补充:RandomAccess接口 表示实现这个接口的类具有随机访问的功能 二、ArrayList与Vector的区别 1、ArrayList不是线程安全的,Vector所有的方法都是线程安全的。 2、二者的底层数据结构都是数组。当ArrayList空间不够时,默认增长50%,当Vector空间不够时,默认增长一倍。 3、Vector可以设置容量增加的参数,ArrayList不可以。 三、HashMap与HashTable的区别 1、HashMap不是线程安全的,HashTable是线程安全的。 2、效率

[多线程] Java线程池应用及原理分析(JDK1.8)

生来就可爱ヽ(ⅴ<●) 提交于 2020-12-13 20:03:00
一 线程池优点   1、线程在创建和销毁时是非常耗费资源的,使用 线程池可以减少创建和销毁线程的次数 ,每个工作线程都可以重复使用。   2、可以根据系统的承受能力,调整线程池中工作线程的数量,防止因为消耗过多内存导致服务器崩溃。   对操作系统来说,创建一个线程的代价是十分昂贵的, 需要给它分配内存、列入调度,同时在线程切换的时候还要执行内存换页,CPU 的缓存被清空。切换回来的时候还要重新从内存中读取信息,破坏了数据的局部性。   关于时间,创建线程使用是直接向系统申请资源的,这里调用系统函数进行分配资源的耗时不好说。   关于资源,Java线程的线程栈所占用的内存是在Java堆外的,所以是不受java程序控制的,只受系统资源限制,默认一个线程的线程栈大小是1M(当让这个可以通过设置 -Xss 属性设置,但是要注意栈溢出问题),但是,如果每个用户请求都新建线程的话,1024个用户光线程就占用了1个G的内存,如果系统比较大的话,一下子系统资源就不够用了,最后程序就崩溃了。   PS:同样的道理在java程序中也不要随意开启新的线程,特别是高频业务尽量使用线程池,不然很容易导致内存不足,程序崩溃的问题。 二 线程池创建    java.uitl.concurrent.ThreadPoolExecutor 类是线程池中最核心的一个类,因此如果要透彻地了解Java中的线程池

Java并发编程:Java原子类

左心房为你撑大大i 提交于 2020-12-13 19:34:47
一、线程不安全 当多个线程访问统一资源时,如果没有做线程同步,可能造成线程不安全,导致数据出错。举例: @Slf4j public class ThreadUnsafe { // 用于计数的统计变量 private static int count = 0 ; // 线程数量 private static final int Thread_Count = 10 ; // 线程池 private static ExecutorService executorService = Executors.newCachedThreadPool(); // 初始化值和线程数一致 private static CountDownLatch downLatch = new CountDownLatch(Thread_Count); public static void main(String[] args) throws Exception{ for ( int i = 0; i < Thread_Count; i++ ) { executorService.execute(() -> { for ( int j = 0; j < 1000; j++) { // 每个线程执行1000次++操作 count ++ ; } // 一个线程执行完 downLatch.countDown(); }); }

java并发:原子类之AtomicLong

旧街凉风 提交于 2020-12-13 16:35:09
原子类之AtomicLong java线程中的操作,需要满足原子性、可见性等原则,比如i++这样的操作不具备原子性, A线程读取了i,另一个线程执行i++,A线程再执行i++就会引发线程安全问题 推荐学习的AtomicInteger和AtomicLong博客 你还在用Synchronized?Atomic你了解不? Java多线程系列--“JUC原子类”02之 AtomicLong原子类 一个非原子性的自加引发的安全例子 下面的例子执行1000个线程,有意思的还Long自加比Interger更容易发现结果是比1000小。 package com.java.javabase.thread.base.concurrent.atomic; import lombok.Data; import lombok.extern.slf4j.Slf4j; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; @Slf4j public class AtomicLongtest { public static void main(String[] args) { AtomicLongtest test =new

ConcurrentHashMap 1.7/1.8

纵饮孤独 提交于 2020-12-13 10:49:24
https://www.cnblogs.com/study-everyday/p/6430462.html JDK1.7的实现 ConcurrentHashMap的数据结构是由一个Segment数组和多个HashEntry组成 每一个Segment元素存储的是HashEntry数组+链表,这个和HashMap的数据存储结构一样 HashEntry大小的计算也是2的N次方(cap <<=1) Segment实现了 ReentrantLock ,也就带有锁的功能, 当执行put操作时,会进行第一次key的hash来定位Segment的位置 这里要进行两次Hash去定位数据的存储位置 计算ConcurrentHashMap的元素大小是一个有趣的问题 第一种方案他会使用不加锁的模式去尝试多次计算ConcurrentHashMap的size,最多三次, 比较前后两次计算的结果,结果一致就认为当前没有元素加入,计算的结果是准确的 第二种方案是如果第一种方案不符合,他就会给每个Segment加上锁,然后计算ConcurrentHashMap的size返回 JDK1.8的实现 直接用Node数组+链表+红黑树的数据结构来实现,并发控制使用Synchronized和CAS来操作 JDK1.8中还能看到Segment的数据结构,但是已经简化了属性, 只是为了兼容旧版本

Atlantis HDU

天涯浪子 提交于 2020-12-13 06:58:25
扫描线的模板题,先把信息接收,然后排序,记录下上边和下边,然后用一条虚拟的线从下往上扫。如果我扫到的是下边,那么久用线段树在这个区间内加上1,表示这个区间现在是有的,等我扫描到上边的时候在加上-1,把之前的消掉,然后线段树维护区间内的长度,这里不是直接用下标维护,而是需要另一个数组来维护,每次记录我当前的下标在原本的图中的长度。 在update部分用一个点表示我这个点以后的一个长度为1的区间,然后这样算出来的sum[1]就是我现在线段树里包括的区间大小,然后用现在的区间大小去乘上这一部分的高度,然后每次相加,就可以了 #include<map> #include < set > #include <ctime> #include <cmath> #include <stack> #include <queue> #include < string > #include <vector> #include <cstdio> #include <cstdlib> #include <cstring> #include <iostream> #include <algorithm> #define lowbit(x) (x & (-x)) typedef unsigned long long int ull; typedef long long int ll; const double

队列:队列在线程池等有限资源池中的应用

给你一囗甜甜゛ 提交于 2020-12-12 21:27:45
1.理解队列? 典型队列,先进者先出的结构,是一种操作受限的线性数据结构。 队列类似栈,基本操作也有两个,入列(尾部插入数据)和出列(头部取出数据) 2.实现队列的方式 类似栈,也可以使用数组和链表来实现队列, 顺序队列:使用数组来实现队列 // 用数组实现的队列 public class ArrayQueue { // 数组:items,数组大小:n private String[] items; private int n = 0; // head 表示队头下标,tail 表示队尾下标 private int head = 0; private int tail = 0; // 申请一个大小为 capacity 的数组 public ArrayQueue(int capacity) { items = new String[capacity]; n = capacity; } // 入队 public boolean enqueue(String item) { // 如果 tail == n 表示队列已经满了 if (tail == n) return false; items[tail] = item; ++tail; return true; } // 出队 public String dequeue() { // 如果 head == tail 表示队列为空 if

Java锁之重入锁(Reentrantlock)原理,公平锁与非公平锁

独自空忆成欢 提交于 2020-12-12 02:45:03
1、特点: 已获取锁的线程再次请求锁,可以直接获取。 2、实现: 自定义内部类 Sync,继承 AbstarctQueuedSynchronizer : 2.1、获取锁 :lock() a、公平锁: acquire(1) b、非公平锁: if (compareAndSetState(0, 1)) //CAS,当前 state 为0,当前线程占有锁:   setExclusiveOwnerThread(Thread.currentThread()); else acquire(1); b.1 AbstarctQueuedSynchronizer acquire(int acquires) 然后是 acquire(1) ——>调用父类 AbstarctQueuedSynchronizer acquire(int acquires) public final void acquire(int arg) { if (!tryAcquire(arg) && acquireQueued(addWaiter(Node.EXCLUSIVE), arg)) selfInterrupt(); } 即如果未获取锁,将请求锁线程加入等待双向队列尾部。然后给当前线程发出中断命令。 Node.EXCLUSIVE = null, addWaiter(Node node) 将 null 加入等待队列尾部,双向队列

动态高并发时为什么推荐ReentrantLock而不是Synchronized?

跟風遠走 提交于 2020-12-11 22:38:09
前言碎语 Synchronized 和 ReentrantLock 大家应该都不陌生了,作为java中最常用的本地锁,最初版本中 ReentrantLock 的性能是远远强于 Synchronized 的,后续java在一次次的版本迭代中 对 Synchronized 进行了大量的优化,直到 jdk1.6 之后,两种锁的性能已经相差无几,甚至 Synchronized 的自动释放锁会更好用。 在面试时被问到 Synchronized 和 ReentrantLock 的使用选择时,很多朋友都脱口而出的说用 Synchronized ,甚至在我面试的时候问面试者,也很少有人能够答出所以然来,moon 想说,这可不一定, 只对标题感兴趣的同学可以直接划到最后 ,我可不是标题党~ Synchronized使用 在 java 代码中 synchronized 的使用 是非常简单的 1.直接贴在方法上 2.贴在代码块儿上 程序运行期间,Synchronized那一块儿代码发生么什么? 来看一张图 在多线程运行过程中, 线程会去先抢对象的监视器 ,这个监视器是对象独有的,其实就相当于一把钥匙,抢到了,那你就获得了当前代码块儿的执行权。 其他没有抢到的线程会进入队列(SynchronizedQueue)当中等待,等待当前线程执行完后,释放锁. 最后当前线程执行完毕后通知出队然后继续重复当前过程.

嗯!这篇多线程不错!伍

大城市里の小女人 提交于 2020-12-11 02:02:58
开篇闲扯 前面几篇写了有关Java对象的内存布局、Java的内存模型、多线程锁的分类、Synchronized、Volatile、以及并发场景下出现问题的三大罪魁祸首。看起来写了五篇文章,实际上也仅仅是写了个皮毛,用来应付应付部分公司“八股文”式的面试还行,但是在真正的在实际开发中会遇到各种稀奇古怪的问题。这时候就要通过线上的一些监测手段,获取系统的运行日志进行分析后再对症下药,比如JDK的jstack、jmap、命令行工具vmstat、JMeter等等,一定要在合理的分析基础上优化,否则可能就是系统小“感冒”,结果做了个阑尾炎手术。 又扯远了,老样子,还是先说一下本文主要讲点啥,然后再一点点解释。本文主要讲并发包JUC中的三个类:ReentrantLock、ReentrantReadWriteLock和StampedLock以及AQS(AbstractQueuedSynchronizer)的一些基本概念。 先来个脑图: Lock接口 public interface Lock { //加锁操作,加锁失败就进入阻塞状态并等待锁释放 void lock(); //与lock()方法一直,只是该方法允许阻塞的线程中断 void lockInterruptibly() throws InterruptedException; //非阻塞获取锁 boolean tryLock(); /