为了账号安全,请及时绑定邮箱和手机立即绑定

处理多线程java程序中的静态变量

处理多线程java程序中的静态变量

繁星淼淼 2021-08-19 21:15:50
下面的工厂类用于获取驱动程序以供执行public class DriverFactory {    //holds the device config    public static Map<String, String> devConfig = new ConcurrentHashMap<>();    //other lines of code follow}此配置从外部数据源加载到 junit 类中,如下所示:@RunWith(ConcurrentTestRunner.class)public class MyTestRunner{    static final int THREAD_COUNT = 1;    @ThreadCount(THREAD_COUNT) @Override @Test    public void run(){        // Devices class returns config for the device        DriverFactory.devConfig = Devices.getConfig()        //other lines of code to perform execution    }}如果其他类在执行过程中需要设备配置,则访问如下:public class MobileActions{    public void swipe(){        String pf = DriverFactory.devConfig.get("Platform");        //other lines of code    }}这种方法(将 devConfig 设为静态)工作正常,只有一个线程。现在,为了支持跨设备并行执行,如果线程数更改为 2,则 devConfig 将始终具有由第二个线程设置的值。为了避免这个问题,如果 devConfig 是非静态的,我们必须在所有其他类中注入这个变量,例如,在上面的 MobileActions 类中。有没有办法让这个变量保持静态但在多线程执行期间仍然有效(每个线程应该处理它自己的 devConfig 副本)。我们还尝试将此变量设为 ThreadLocal<>,但这也无济于事。
查看完整描述

3 回答

?
米脂

TA贡献1836条经验 获得超3个赞

将 DriverFactory 中的 devConfig 设为私有。为它提供 getter 和 setter。如果您需要它特定于线程,请将其设为 threadlocal。


public class DriverFactory {


    // holds the device config

    private static final ThreadLocal<Map<String, String>> devConfig = ThreadLocal

        .withInitial(ConcurrentHashMap::new);


    public static String getDevConfig(String key) {

        return this.devConfig.get().get(key);

    }


    public static void setDevConfig(Map<String, String> config) {

        this.devConfig.get().putAll(config);

   }

}


查看完整回答
反对 回复 2021-08-19
?
慕雪6442864

TA贡献1812条经验 获得超5个赞

您可以将 devConfig 包装到 ConcurrentHashMap 中:


public class DriverFactory {

    //holds the device config

    private static final String CONFIG_KEY = "config_key";

    private static final ConcurrentHashMap<String, Map<String, String>> devConfig = new ConcurrentHashMap<>();


    public static Map<String, String> setDevConfig(Map<String, String> devConfig) {

        return DriverFactory.devConfig.putIfAbsent(CONFIG_KEY, devConfig);

    }


    public static Map<String, String> getDevConfig() {

        return DriverFactory.devConfig.get(CONFIG_KEY);

    }


    //other lines of code follow

}


@RunWith(ConcurrentTestRunner.class)

public class MyTestRunner{

    static final int THREAD_COUNT = 1;


    @ThreadCount(THREAD_COUNT) @Override @Test

    public void run(){

        // Devices class returns config for the device

        DriverFactory.setDevConfig(Devices.getConfig())

        //other lines of code to perform execution

    }

}


public class MobileActions{

    public void swipe(){

        String pf = DriverFactory.getDevConfig().get("Platform");

        //other lines of code

    }

}

但是如果你想执行Devices.getConfig()一次,你应该尝试java.util.concurrent.ConcurrentHashMap#computeIfAbsent或自定义锁定。就像是:


    public static Map<String, String> getDevConfig() {

        return DriverFactory.devConfig

                .computeIfAbsent(CONFIG_KEY, s -> Devices.getConfig());

    }


查看完整回答
反对 回复 2021-08-19
  • 3 回答
  • 0 关注
  • 337 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信