异步赋值

简介

同步赋值就是我们最常用的方式


public class Test {
    public static void main(String[] args) {
        Test test = new Test();
        test.setValue("123");
        System.out.println(test.getValue());
        
    }
    private String value;

    public String getValue() {
        return value;
    }

    public void setValue(String value) {
        this.value = value;
    }
}

其中test对象中的value set 赋值 get取值。这个在单线程中是没问题的。
但是假如说变成多线程呢。


public class Test {
    public static void main(String[] args) {
        Test test = new Test();
        new Thread(() -> {
            //1赋值
            test.setValue("123");
        }).start();
        //2获取值
        System.out.println(test.getValue());
    }

    private String value;

    public String getValue() {
        return value;
    }

    public void setValue(String value) {
        this.value = value;
    }
}

这种情况赋值与获取值,就没办法保证先后顺序。获取值的时候有可能另一个线程还没有赋值,或者,已经赋值,但线程间的缓存还不一致。

那线程间的值同步该怎么做?

方案一 synchronized

package com.hcq.async;

/**
 * 同步方法一
 */
public class Model1 {
    //使用volatile 防止线程缓存
    private volatile String value;

    public synchronized String getValue() {
        try {
            this.wait();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return value;
    }

    public synchronized void setValue(String value) {
        //先赋值,再同步
        this.value = value;
        this.notify();
    }
}

这种方案是最简单的一步方案。
缺点:

  • 锁比较重
  • 多次赋值有些问题。
  • 如果赋值线程在先,会出现死锁问题。

方案二 synchronized+ volatile

public class Model2 {
    //使用volatile 防止线程缓存
    private volatile String value;

    private volatile boolean isOk = false;

    public synchronized String getValue() {
        try {
            this.wait();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return value;
    }

    public synchronized void setValue(String value) {
        if (this.isOk == true) {
            System.out.println("已经赋值[" + this.value + "],赋值【" + value + "]失败!");
        } else {
            //先赋值,再同步
            this.isOk = true;
            this.value = value;
            System.out.println("赋值[" + this.value+"]");
            this.notify();
        }

    }
}

这种方案解决了多次赋值问题。

  • 锁比较重
  • 如果赋值线程在先,会出现死锁问题。

方案三 CountDownLatch + Cas

public class Model3 {
    //使用volatile 防止线程缓存
    private volatile String value;
    private AtomicBoolean isOk = new AtomicBoolean(false);

    private CountDownLatch lock = new CountDownLatch(1);

    public String getValue() {
        try {
            lock.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return value;
    }

    public void setValue(String value) {
        //幂等操作
        if (isOk.compareAndSet(false, true)) {
            //先赋值,再同步
            this.value = value;
            System.out.println("赋值[" + this.value+"]");
            this.lock.countDown();
        } else {
            System.out.println("已经赋值[" + this.value + "],赋值【" + value + "]失败!");
        }
    }
}

用AtomicBoolean 来解决重复调用的幂等问题。
用CountDownLatch解决 先赋值死锁问题。

代码: https://github.com/jlhuang9/iptest/tree/master/src/main/java/com/hcq/async

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
React TransitionGroup 是 React 提供的一个组件,用于管理组件的进入和离开动画。它可以帮助我们实现一些比较复杂的动画效果,比如在列表中添加或删除元素时,让新元素平滑地进入,旧元素平滑地离开。 如果你想要实现异步赋值自动上下滚动的效果,可以使用 React TransitionGroup 结合 CSS 的方式来实现。具体的步骤如下: 1. 在组件的 state 中定义一个数组,用于存储需要显示的数据。 2. 在组件的 componentDidMount 方法中,使用定时器或者异步请求来更新这个数组,并且设置一个状态值 isScrolling 为 true,表示当前正在自动滚动。 3. 在组件的 componentDidUpdate 方法中,判断 isScrolling 是否为 true,如果是,则使用 React TransitionGroup 包裹一个滚动容器,并且使用 CSS 来实现自动滚动的效果。 4. 在 CSS 中定义一个动画,用于实现自动滚动的效果。可以使用 transform 和 transition 属性来实现。 下面是一个示例代码: ```jsx import React, { Component } from 'react'; import { TransitionGroup, CSSTransition } from 'react-transition-group'; class AutoScroll extends Component { state = { data: [], isScrolling: false, }; componentDidMount() { // 模拟异步请求数据 setTimeout(() => { this.setState({ data: ['数据1', '数据2', '数据3'], isScrolling: true }); }, 1000); } componentDidUpdate() { if (this.state.isScrolling) { // 自动滚动 this.scrollContainer.scrollTop = this.scrollContainer.scrollHeight; } } render() { const { data, isScrolling } = this.state; return ( <div className="scroll-container" ref={(node) => { this.scrollContainer = node; }} > <TransitionGroup> {data.map((item) => ( <CSSTransition key={item} timeout={500} classNames="fade"> <div>{item}</div> </CSSTransition> ))} </TransitionGroup> {isScrolling && ( <style> {` .scroll-container { height: 200px; overflow: hidden; } .fade-enter { transform: translateY(-100%); } .fade-enter-active { transform: translateY(0); transition: transform 500ms ease-in-out; } .fade-exit { transform: translateY(0); } .fade-exit-active { transform: translateY(100%); transition: transform 500ms ease-in-out; } `} </style> )} </div> ); } } export default AutoScroll; ``` 在这个示例中,我们使用了 TransitionGroup 和 CSSTransition,来实现进入和离开动画效果。在 CSS 中,我们定义了一个名为 fade 的动画,用于实现自动滚动的效果。通过 translateY 属性将元素移动到指定位置,并且使用 transition 属性来实现平滑过渡的效果。最后,在组件的 render 方法中,我们将滚动容器的 ref 绑定到 this.scrollContainer 上,以便在组件的 componentDidUpdate 方法中使用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值