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

下面的工厂类用于获取驱动程序以供执行


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<>,但这也无济于事。


繁星淼淼
浏览 338回答 3
3回答

米脂

将 DriverFactory 中的 devConfig 设为私有。为它提供 getter 和 setter。如果您需要它特定于线程,请将其设为 threadlocal。public class DriverFactory {&nbsp; &nbsp; // holds the device config&nbsp; &nbsp; private static final ThreadLocal<Map<String, String>> devConfig = ThreadLocal&nbsp; &nbsp; &nbsp; &nbsp; .withInitial(ConcurrentHashMap::new);&nbsp; &nbsp; public static String getDevConfig(String key) {&nbsp; &nbsp; &nbsp; &nbsp; return this.devConfig.get().get(key);&nbsp; &nbsp; }&nbsp; &nbsp; public static void setDevConfig(Map<String, String> config) {&nbsp; &nbsp; &nbsp; &nbsp; this.devConfig.get().putAll(config);&nbsp; &nbsp;}}

慕雪6442864

您可以将 devConfig 包装到 ConcurrentHashMap 中:public class DriverFactory {&nbsp; &nbsp; //holds the device config&nbsp; &nbsp; private static final String CONFIG_KEY = "config_key";&nbsp; &nbsp; private static final ConcurrentHashMap<String, Map<String, String>> devConfig = new ConcurrentHashMap<>();&nbsp; &nbsp; public static Map<String, String> setDevConfig(Map<String, String> devConfig) {&nbsp; &nbsp; &nbsp; &nbsp; return DriverFactory.devConfig.putIfAbsent(CONFIG_KEY, devConfig);&nbsp; &nbsp; }&nbsp; &nbsp; public static Map<String, String> getDevConfig() {&nbsp; &nbsp; &nbsp; &nbsp; return DriverFactory.devConfig.get(CONFIG_KEY);&nbsp; &nbsp; }&nbsp; &nbsp; //other lines of code follow}@RunWith(ConcurrentTestRunner.class)public class MyTestRunner{&nbsp; &nbsp; static final int THREAD_COUNT = 1;&nbsp; &nbsp; @ThreadCount(THREAD_COUNT) @Override @Test&nbsp; &nbsp; public void run(){&nbsp; &nbsp; &nbsp; &nbsp; // Devices class returns config for the device&nbsp; &nbsp; &nbsp; &nbsp; DriverFactory.setDevConfig(Devices.getConfig())&nbsp; &nbsp; &nbsp; &nbsp; //other lines of code to perform execution&nbsp; &nbsp; }}public class MobileActions{&nbsp; &nbsp; public void swipe(){&nbsp; &nbsp; &nbsp; &nbsp; String pf = DriverFactory.getDevConfig().get("Platform");&nbsp; &nbsp; &nbsp; &nbsp; //other lines of code&nbsp; &nbsp; }}但是如果你想执行Devices.getConfig()一次,你应该尝试java.util.concurrent.ConcurrentHashMap#computeIfAbsent或自定义锁定。就像是:&nbsp; &nbsp; public static Map<String, String> getDevConfig() {&nbsp; &nbsp; &nbsp; &nbsp; return DriverFactory.devConfig&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .computeIfAbsent(CONFIG_KEY, s -> Devices.getConfig());&nbsp; &nbsp; }
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java