Java Concurrency Note2

不可变对象

final

  • 修饰方法、类、变量
  • 修饰类:不能被继承
  • 修饰方法:1、锁定方法不被继承类修改 2、效率(老版本)
  • 修饰变量:基本数据类型不能再修改、引用类型变量不能再指向其他,但是指向的对象本身可能会发生改变
  • 我的理解是本质final锁的是栈而不是堆

Collections.unmodifiablexxx/Guava:Immutablexxx

  • 提供不可变的方法

unmodify

unmodifiable源码:使所有改变map的操作抛出异常(如下)

 @Override
        public V putIfAbsent(K key, V value) {
            throw new UnsupportedOperationException();
        }

        @Override
        public boolean remove(Object key, Object value) {
            throw new UnsupportedOperationException();
        }

        @Override
        public boolean replace(K key, V oldValue, V newValue) {
            throw new UnsupportedOperationException();
        }

        @Override
        public V replace(K key, V value) {
            throw new UnsupportedOperationException();
        }

Guava:Immutablexxx 同样会抛出异常,还会提示弃用

immutable

线程封闭

把对象封装到一个线程中,只对一个线程可见,即保证了安全性

  • Ad-hoc:程序控制实现,不推荐
  • 堆栈封闭:局部变量,无并发问题,因为变量在线程私有的栈中
  • ThreadLocal(有机会再好好学学)

线程不安全类

StringBuilder & StringBuffer

public class StringExample1 {
    public static int clientTotal = 5000;
    public static int threadTotal = 200;
//    public static StringBuilder sb = new StringBuilder();
    public static StringBuffer sb = new StringBuffer();

    public static void main(String[] args) throws Exception{
        ExecutorService executorService = Executors.newCachedThreadPool();
        final Semaphore semaphore = new Semaphore(threadTotal);
        final CountDownLatch countDownLatch = new CountDownLatch(clientTotal);
        for (int i = 0; i<clientTotal; i++){
            executorService.execute(()->{
                try {
                    semaphore.acquire();
                    update();
                    semaphore.release();
                }catch (Exception e){
                    log.error("exception",e);
                }
                countDownLatch.countDown();
            });
        }
        countDownLatch.await();
        executorService.shutdown();
        log.info("size:{}",sb.length());
    }

    private static void update(){
        sb.append("t");
    }
}

StringBuffer线程安全,观察源码(都加了synchronized关键字)

@Override
    public synchronized int length() {
        return count;
    }

    @Override
    public synchronized int capacity() {
        return value.length;
    }


    @Override
    public synchronized void ensureCapacity(int minimumCapacity) {
        super.ensureCapacity(minimumCapacity);
    }

    /**
     * @since      1.5
     */
    @Override
    public synchronized void trimToSize() {
        super.trimToSize();
    }

    /**
     * @throws IndexOutOfBoundsException {@inheritDoc}
     * @see        #length()
     */
    @Override
    public synchronized void setLength(int newLength) {
        toStringCache = null;
        super.setLength(newLength);
    }

由上可见,线程有损耗

SimpleDateFormat & JodaTime

  • Copyrights © 2019-2020 Rex