Java多线程学习(三)Atomic原子变量学习 线程安全委托

要让一个类是线程安全的,可以将这个任务委托给类中的状态变量,让这些状态变量成为线程安全的,那么这个类也就是线程安全的了。

比如一个响应事件的类,鼠标事件和键盘事件是完全无关的,也就是说这连个变量是彼此独立的,那么可以将类的线程安全委托给这两个变量。

public class VisualComponent {
    private final List<KeyListener> KeyListeners = new CopyOnWriteArrayList<KeyListener>();
    private final List<MouseListener> MouseListeners = new CopyOnWriteArrayList<MouseListener>();

    public void addKeyListener(KeyListener keyListener){
        KeyListeners.add(keyListener);
    }
    public void addMouseListener(MouseListener mouseListener){
        MouseListeners.add(mouseListener);
    }

}

通过CopyOnWriteArrayList这个线程安全的集合类将两个状态变量设置为线程安全的。保证了整个类是线程安全的。

 

再比如连个状态变量有联系的。定义一个数值区间的类,也就是值域,当改变值域时,设置值域上限时要大于当时的最小值,设置值域下限时要小于当时的最大值。这样两个变量就有了联系,当我们把类的线程安全委托给这两个变量时,就会出现问题。

public class NumberRange {
    private final AtomicInteger lower = new AtomicInteger(0);
    private final AtomicInteger upper = new AtomicInteger(10);

    public void setLower(int i ){
        if (i > upper.get()){
            throw new IllegalArgumentException(i+"不能比大数大!");
        }
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        lower.set(i);
        System.out.println("设置成功!"+lower.get());
    }
    public void setUpper(int i){
        if (i < lower.get()){
            throw new IllegalArgumentException(i+"不能比小数小!");
        }

        upper.set(i);
        System.out.println("设置成功!"+upper.get());
    }
    public void getRange(){
        System.out.println("区间"+lower+"--"+upper);
    }

    public static void main(String[] args) {
        NumberRange numberRange = new NumberRange();
        new Thread(new Runnable() {
            @Override
            public void run() {
                numberRange.setLower(5);
            }
        }).start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                numberRange.setUpper(4);
            }
        }).start();
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        numberRange.getRange();
    }
}

 

可以看到出现了问题,两个线程,值域初始值是0-10,第一个线程想把值域下限设置为5,满足判断小于上限10,但是判断完了让他休眠1秒,此时CPU被第二个线程抢去,第二个线程想把上限设置为4,满足大于下限0,将上限设置为4,第二个线程执行完之后第一个线程继续执行,将下限设置为了5。

 

总结:如果一个类由多个彼此独立的线程安全的状态变量组成,并且类的操作不包含无效状态转换,那么可以将线程安全委托给这些状态变量。

如果一个状态变量是线程安全的,没有任何不变约束限制他的值,并且没有任何状态转换限制他的操作,那么他可以被安全发布。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值