【自旋锁】

作者:Leopold    访问量:12

1 自旋锁与互斥锁

1.1 定义

  • 场景:双核(core0,core1)双线程(A,B),core0处理线程A,core1处理线程B。A线程获取锁,锁被B线程持有。
  • 互斥锁:sleep-waiting型,A线程则进入等待状态,core0处理其他任务。
  • 自旋锁:busy-waitting型,A线程在core0核上持续进行锁请求,直到B线程释放锁。

1.2 区别

  • 互斥锁:初始开销较大,但锁持续时间与互斥锁开销没有影响
  • 自旋锁:初始开销小,但死循环检测并加锁,消耗cpu。随着持锁时间的增加,加锁开销呈线性增长趋势。

【ArrayList】数组

作者:Leopold    访问量:1

数组

1 ArrayList

ArrayList是一个采用类型参数的泛型类。

1.1 声明

//构造一个保存App对象的数组列表 ArrayList<App> staff = new ArrayList<App>();  //Java SE 7中,可以省去右边的类型参数 ArrayList<App> staff = new ArrayList<>();

在Java SE 5 前没有泛型类,因此原先的ArrayList保存的是一个Object类的元素,他是自适应大小的集合。在老版本中,程序员一般使用Vector类实现动态数组,但其实ArrayList更有效。

1.2 函数

1.2.1 add(int index,E obj)、remove(int index)
staff.add(new App());
staff.add(0,new App()); //指定位置
staff.remove(0);

如果经常在中间插入或者删除元素,对于数组元素较多而言,应使用链表。

add方法会面临空间不足的问题。如果已满,会自动创建更大的数组,并将所有的对象从较小的数组中拷贝到较大的数组中去,下面是ArrayList中,自增的源码。

private void grow(int minCapacity) {
    // overflow-conscious code
    int oldCapacity = elementData.length;
    int newCapacity = oldCapacity + (oldCapacity >> 1); //右移运算,扩大1.5倍。
    if (newCapacity - minCapacity < 0)
        newCapacity = minCapacity;
    if (newCapacity - MAX_ARRAY_SIZE > 0)
        newCapacity = hugeCapacity(minCapacity);
    // minCapacity is usually close to size, so this is a win:
    elementData = Arrays.copyOf(elementData, newCapacity);
}

如果已知要存储元素的个数,可用staff.ensureCapacity(int initCapacity)声明,这样即便调用add方法100次,也不用重新分配空间。但需要注意区别于为新数组分配空间,代码如下:

package com.tyq;

import java.util.ArrayList;
import java.util.Arrays;

public class Sys {
    public static void main(String[] args) {
        ArrayList<Integer> num1 = new ArrayList<>(100); //默认是10
        System.out.println("num1:" + num1); 
        //num1:[]
        
        Integer[] num2 = new Integer[10];
        System.out.println("num2:" + Arrays.toString(num2));
        //num2:[null, null, null, null, null, null, null, null, null, null]
    }
}

分配100个元素的存储空间,数组就会有100个空位置等待使用,而容量为100的数组列表只是拥有保存100个元素的潜力,但在最初初始化时,数组列表根本不含有任何元素。

1.2.2 size()

返回数组列表中实际元素数目

1.2.3 trimToSize()

一旦确认数组列表的大小不再发生变化,通过调用trimToSize()方法,将存储区域的大小调整为当前元素数量所需的存储空间数目,最后GC回收多余的存储空间。使用后避免再次添加新元素,因为移动存储块会花费时间。

1.2.4 set(int index,E obj)、get(int index)

set方法覆盖原有内容。