设计线程安全的类

步骤:

找出构成对象状态的所有变量

找出约束状态变量的不变性条件

建立对象状态的并发访问策略

1.在现有的线程安全类中添加功能

(1)重用能减低工作量和提高正确性

(2)如果底层的类改变了同步策略,使用不同的锁来保护它的状态,则子类会被破坏

class BetterVector<E> extends Vector<E>{
    public  synchronized boolean putIfAbsent(E e){
        boolean absent = !contains(e);
        if(absent){
            add(e);
        }
        return absent;
    }
}

2.客户端加锁机制

(1)对于使用对象X的客户端,如果知道X使用的是什么锁,则使用X本身用于保护其状态的锁,来保护这段客户端代码

(2)同样会破坏同步策略的封装

A.错误示例:

class ListHelper<E>{
    public List<E> list = Collections.synchronizedList(new ArrayList<E>());

    public synchronized boolean putIfAbsent(E e){
        boolean absent = !list.contains(e);
        if(absent){
            list.add(e);
        }
        return absent;
    }
}

B.正确示例:

class ListHelper<E>{
    public List<E> list = Collections.synchronizedList(new ArrayList<E>());

    public  boolean putIfAbsent(E e){
        synchronized(list){
            boolean absent = !list.contains(e);
            if(absent){
                list.add(e);
            }
            return absent;
        }
    }
}

3.组合:推荐方式

class ImprovedList<E> implements List<E>{
    private final List<E> list;
    public ImprovedList(List<E> list){
        this.list = list;
    }

    public synchronized boolean putIfAbsent(E e){
            boolean absent = !list.contains(e);
            if(absent){
                list.add(e);
            }
            return absent;
       }

    public synchronized  boolean add(E e) {
        //委托.....

    }
}
时间: 2024-10-20 00:49:15

设计线程安全的类的相关文章

Java 并发编程(三)设计线程安全的类-实例封闭

到目前为止,我们已经介绍了关于线程安全与同步的一些基础知识.然而,我们并不希望对每一次内存访问都进行分析以确保是线程安全的,而是希望将一些现有的线程安全组件组合为更大规模的组合为更大规模的组件或程序.之后,我们会讲一些设计线程安全类的一些基本概念,介绍一些组合模式. 一.设计线程安全的类 在设计线程安全类的过程中,需要包含以下三个基本要素: 1.找出构成对象状态的所有变量 2.找出约束状态变量的不变性条件 3.建立对象状态的并发访问管理策略 要分析对象的状态,首先从对象的域开始.如果对象中所有的

Java并发编程实战(chapter_2)(对象发布、不变性、设计线程安全类)

又是三星期的生活.感觉自从有了这个分享之后,会无形多了一份动力,逼着自己不能落后,必须要去不停的学习,这其实是我想要的,各位少年团中的成员也都是有共鸣的,在此很感动,省去一万字.....这一次会总结对象的安全发布.不变性,这几点,在我们工程实践中,同样也是非常具有参考与思考价值的基础知识点.看书枯燥,理解生涩,可是当你看过,理解一点,再平时业务代码中就会比别人多思考一分,就会比别人在更"恶劣"的网络环境中,更稳定一分.这几天想起<三傻>中,那句很经典的话:追求卓越,成功将会

java多线程3.设计线程安全类

实例封闭:将数据封装在对象中,将数据的访问限制在对象的方法上,确保线程在访问数据时总能持有正确的锁 java平台的类库中有很多线程封闭的示例,其中一些类的唯一用途就是将非线程安全的类转为线程安全的类.一些基本的容器类并非线程安全,如ArrayList和HashMap,但类库提供了包装器工厂方法,如Collections.synchronizedList,使这些非线程安全的类可以在多线程环境中安全地使用. 这些工厂方法通过"装饰器"模式将容器类封装在一个同步的封装器对象中,包装器将接口中

Java线程池工具类

使用线程池的好处: 重用线程,线程的创建和销毁是很耗时的. 控制线程的数量. 线程池工具类: ThreadPool.java package com.zws.thread.pool; import java.util.concurrent.Callable; import java.util.concurrent.Future; /**  *   * @author wensh.zhu  *  */ public interface ThreadPool { void execute(Runna

Java多线程——线程阻塞工具类LockSupport

简述 LockSupport 是一个非常方便实用的线程阻塞工具,它可以在线程内任意位置让线程阻塞. 和 Thread.suspend()相比,它弥补了由于 resume()在前发生,导致线程无法继续执行的情况. 和 Object.wait()相比,它不需要先获得某个对象的锁,也不会抛出 InterruptedException 异常. LockSupport 的静态方法 park()可以阻塞当前线程,类似的还有 parkNanos().parkUntil()等方法.它们实现了一个限时等待,如下图

深刻理解Java中final的作用(一):从final的作用剖析String被设计成不可变类的深层原因

声明:本博客为原创博客,未经同意,不得转载!小伙伴们假设是在别的地方看到的话,建议还是来csdn上看吧(原文链接为http://blog.csdn.net/bettarwang/article/details/26744661),看代码和提问.讨论都更方便. Java中final的作用主要表如今三方面:修饰变量.修饰方法和修饰类.以下就从这两个方面来解说final的作用.在文末从final及类的设计安全性出发,论述了Java中String为何要被设计成不可变类. 1.final修饰变量 fina

多线程(二)构建线程安全的类

构建线程安全的类 volatile 只保证数据可见性,不保证数据同步.也就是说,JVM只保证使用了volatile的数据变更后对所有线程暴露最新值,并不会对线程内部缓存数据的操作多限制.多线程同时变更某个共享的volatile数据并不会产生正确结果. 在满足以下条件时,可使用volatile: 1.写入变量时并不依赖变量当前值:或者能确保只有单一的线程修改变量的值. 2.变量不需要与其他变量共同参与不变约束. 3.访问变量时,没有其他原因需要加锁. long和double 64位数据,分为上下3

获取当前线程状态--Thread类

String msgToPrint = Thread.currentThread().getStackTrace()[3] .getMethodName(); 就是调用时的方法名. 其中使用的Thread类的第一个方法: public static Thread currentThread() 返回当前线程对象. 实例代码: package com.loaderman.getthreadstatusdemo; import android.support.v7.app.AppCompatActi

JAVA 并发编程-线程同步工具类(十二)

本文主要介绍一些java线程同步工具类,并不进行具体讲解,当有需要时,可以再去结合实例学习. 信号灯(Semaphore) 应用场景举例: 例如公司的打卡系统,如果有一个打卡机,那么一次就只能有一个人打卡,其余的人就被阻塞住,打卡完以后就可由下一个人打卡.如果有3个打卡机,那么一次就允许3个人或者少于三个人打卡,其余的人就得等待打卡机空闲下来才能继续打卡. 结果: 已进入1个线程,还可进入2个 已进入2个线程,还可进入1个 已进入3个线程,还可进入0个 空余出1个 已进入4个线程,还可进入0个