以静态和非静态方法返回相同的生成的UUID

时间:2018-11-19 10:01:15

标签: java multithreading

我有一个这样定义的对象:

TestDriver.java

public void TestDriver extends FirefoxDriver implements SupportDownloads{

    public TestDriver(){
        super(TestDriver.service(), TestDriver.options());
    }

    private static service(){
        // implementation
    }

    private static options(){
        ..
        // attempting to generate a UUID which will be eventually be set as the folder where all downloads will go to. 
        // unique paths are needed as we will be using this class for multi-threaded runs and would like each browser to have its own unique download folder
        byte[] value = String.valueOf(Thread.currentThread().getId()).getBytes());
        String uniqueID = UUID.nameUUIDFromBytes(value).toString();
        ..
    }

    // purpose of this method is to return the path download folder 
    // note the repeated generation of the UUID because the above methods are static
    @Override
    public File getDownloadPath(){
        String value = String.valueOf(Thread.currentThread().getId());
        return new File(prop.getProperty(fileDirectory()) + File.separator + UUID.nameUUIDFromBytes(value.getBytes()));    
    }
}

SupportsDownload.java

public interface SupportsDownload {
    public File getDownloadPath();
}

我想做的是:

  1. 生成UUID,以便创建的每个线程都有唯一的下载路径
  2. 为了也可以在此类之外可以访问的公共方法中返回此UUID(用于单元测试和用户使用)

即使上面的代码已经起作用,我也会遇到official Java docs提到的一个问题:

  

返回此线程的标识符。线程ID是创建此线程时生成的正整数。线程ID是唯一的,并且在其生命周期内保持不变。 线程终止时,该线程ID可以重新使用。

因此,上述方法并不是万无一失的,因为仅将UUID种子基于Thread.currentThread()。getId()如果被重用可能会产生相同的ID,从而导致生成的UUID相同。

然后我尝试将其修改为以毫秒为单位,即:

        byte[] value = String.valueOf(Thread.currentThread().getId() + Calendar.getInstance().getTimeInMillis()).getBytes());

但是,由于时间值总是在变化,因此我无法在返回方法getDownloadPath()中获取完全相同的值。

如果我只生成一次时间值,并将其存储在变量中,即:

private final long timeInMillis = Calendar.getTime().getTimeInMillis();

我将无法同时使用此变量进行静态和非静态方法。

我很茫然,任何建议都会很棒:-)

1 个答案:

答案 0 :(得分:1)

我相信您应该使用ThreadLocal来完成任务。在下面,我添加了示例代码。

public class Main {

    public static void main(String[] args) {
        Thread t1 = new Thread(() -> {
            MyUUIDFactory.getUUIDPerThread();
            MyUUIDFactory.getUUIDPerThread();
        }, "My Thread-1");

        Thread t2 = new Thread(() -> {
            MyUUIDFactory.getUUIDPerThread();
            MyUUIDFactory.getUUIDPerThread();
        }, "My Thread-2");

        t1.start();
        t2.start();
    }

}

class MyUUIDFactory {
    private static final ThreadLocal<String> localWebDriver = ThreadLocal.withInitial(
            () -> UUID.randomUUID().toString());

    public static String getUUIDPerThread() {
        return localWebDriver.get();
    }
}