关于JAVA高并发相关学习

参考书籍:《实战JAVA高并发程序设计》本文仅用于自己参考
一、概念

  • 同步(Synchronous)和异步(Asynchronous)
    在这里插入图片描述
  • 并发(Concurrency)和并行(Parallelism)
    在这里插入图片描述
  • 临界区
    临界区用来表示一种公共资源或者说是共享数据,可以被多个线程使用。但是每一次,只能有一个线程使用它,一旦临界区资源被占用,其他线程想要使用这个资源就必须等待。
  • 阻塞(Blocking)和非阻塞(Non-Blocking)
    在这里插入图片描述
  • 死锁(DeadLock)、饥饿(Starvation)和活锁(Livelock)
    死锁就是多个线程之间,相互占用对方需要的资源而都不进行释放,导致彼此之间相互等待对方释放资源,产生无限制等待的现象。
    在这里插入图片描述

二、Java并行程序基础
1、线程就是轻量级的进程,是程序执行的最小单位,使用多线程而不是用多线程去进行兵法程序的设计,是因为线程间的切换和调度的成本远远小于进程。
在这里插入图片描述

2、wait()和notify()的工作流程细节
在这里插入图片描述

3、volatile与java内存模型
java内存模型具有原子性、有序性、可见性。
通过关键字volatile来修饰的变量为共享变量,有不断被修改的风险。

4、synchronized
关键字synchronized的作用是实现线程间的同步,他的工作是对同步的代码加锁,使得每一次只能有一个线程进入同步块,从而保证线程间的安全性。
关键字sychronized的用法

  • 指定加锁对象:对给定对象加锁,进入同步代码前要获得给定对象的锁
  • 直接作用于实例方法:相当于对当前实例加锁,进入同步代码前要获得当前实例的锁
  • 直接作用于静态方法:相当于对当前类加锁,进入同步代码前要获取当前类的锁

5、ArrayList与Vector
多线程情况下,ArrayList会导致程序出错,因为ArrayList是一个线程不安全的容器
使用Vecotr代替ArrayList即可

6、HashMap与ConcurrentHashMap
HashMap同样不是线程安全的
使用ConcurrentHashMap代替HashMap

7、加锁问题
多线程间,对于在变的对象加锁,会导致对临界区代码控制出现问题。
synchronized加锁在Integer等变量上,会产生诡异问题,原因是Integer不能改变值,参考valueOf等方法,都是通过new Integer()返回的,所以针对加锁问题,应该加在同一个对象上。

8、线程复用:线程池
线程池中提供一定数量的线程,外部调用需要创建线城时,从线程池中获取空闲的线程;当外部使用线程完成后需要关闭线程时,只需要把线程放回线程池。JDK提供了一套Executor框架对线程进行有效的控制。java.util.concurrent包中,是JDK并发包的核心类

三、JDK并发包
java.util.concurrent包中
ConcurrentHashMap:这是一个高效的并发HashMap,是一个线程安全的HashMap;
CopyOnWriteArrayList:这是一个List,读多写少的场合,这个List性能非常好,远远好于Vector;
ConcurrentLinkedQueue:高效的并发队列,使用链表实现,可以看做是线程安全的LinkedList;
BlockingQueue:这是一个接口,JDK内部通过链表、数组等方式实现了这个接口,标识阻塞队列,非常适合用于作为数据共享的通道;
ConcurrentSkipListMap:跳表的实现,这是一个map,使用跳表的数据结构进行快速查找。
1、HashMap
如果需要一个线程安全的HashMap,可以通过Collections.synchronizedMap()方法实现,产生一个名为SynchronizedMap的map,它使用托管,将自己所有Map相关的功能交给传入的hashMap实现,而自己则主要负责保证线程安全。
public static Map map = Collections.synchronizedMap(new HashMap());

一个更加专业的并发HashMap是ConcurrentHashMap,专门为并发进行了性能优化,跟适合多线程场景。

2、List
ArrayList 和Vector都是使用数组作为其内部实现,不同的是,Vector是线程安全的。
LinkedList使用链表的数据结构实现了List,但也不是线程安全的,但可以通过Collections.synchonizedList()方式实现线程安全。

3、ConcurrentLinkedQueue
队列Queue也是常用的数据结构之一,ConcurrentLinkedQueue是用来实现高并发的队列,使用链表数据结构。

4、CopyOnWriteArrayList
很多场景中,读操作可能会远远大于写操作,读操作是安全的,但遇见写-写操作或者读-写操作时,并发量大的情况下就会有不一致的情况产生。CopyOnWriteArrayList类读取是完全不加锁的,写入也不会阻塞读取操作,只有写入-写入之间需要同步等待。因为在写入操作时,会进行一次自我复制。写完之后,再将复制替换原来的数据,其他线程读取会立刻察觉,因为array变量是volatile类型。

四、并行模式与算法
1、单例模式:一种创建对象的模式,用于产生一个对象的具体实例。确保系统中一个类只产生一个实例。
好处1:对于频繁的使用对象,可以省略new操作花费的时间,这对于重量级对象而言,节省了一笔很可观的开销。
好处2:由于new操作的减少,对系统内存的使用频率也会降低,这将减轻GC的压力,缩短GC停顿时间。

不变模型:类似String类、基础类型的封装类型,使用final关键字对类进行修饰
final修饰属性,确保属性只有一次赋值后就永远不会发生改变;
对class进行修饰,确保了类不会有子类。

2、生产者-消费者模式
核心是共享内存缓存区,是生产者和消费者之间的桥梁,避免两者直接通信,对两者进行解耦。

3、算法:
搜索:二分法
排序:冒泡排序(冒泡迭代排序、奇偶交换排序)、希尔排序 import java.util.concurrent.CountDownLatch;
public class bubbleSort {

//方法一
public static int[] bubbleSort(int[] array) {
    Long begin = System.currentTimeMillis();
    for (int i = array.length - 1; i > 0; i--) {
        for (int j = 0; j < i; j++) {
            if (array[j] > array[j + 1]) {
                int temp = array[j];
                array[j] = array[j + 1];
                array[j + 1] = temp;
            }
        }
    }
    System.out.println(System.currentTimeMillis() - begin);
    return array;
}

//方法二:【串行】奇偶交换排序exchFlag:记录当前迭代是否发生了数据交换;start记录是奇交换还是偶交换
public static int[] oddEventSort(int[] arr) {
    Long begin = System.currentTimeMillis();
    int exchFlag = 1, start = 0;
    while (exchFlag == 1 || start == 1) {
        exchFlag = 0;
        for (int i = start; i < arr.length - 1; i += 2) {
            if (arr[i] > arr[i + 1]) {
                int temp = arr[i];
                arr[i] = arr[i + 1];
                arr[i + 1] = temp;
                exchFlag = 1;
            }
        }
        if (start == 0) {
            start = 1;
        } else {
            start = 0;
        }

    }
    System.out.println(System.currentTimeMillis() - begin);

    return arr;
}

//希尔排序
public static int[] insertSort(int[] arr){
    int length = arr.length ;
    int i , j , key ;
    for(i = 1 ; i < length ; i++){
       key = arr[i];
       j = i-1 ;
       while (j >= 0 && arr[j] > key){
           arr[j + 1] = arr[j];
           j-- ;
       }
       arr[j+1] = key ;
    }
    return arr ;
}

}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值