Java 每个线程一个随机实例,由原始随机实例播种以获得再现性

Java 每个线程一个随机实例,由原始随机实例播种以获得再现性,java,random,distribution,uniform-distribution,Java,Random,Distribution,Uniform Distribution,我需要做1000计算,每一个都基于一个随机数。 整个运行需要可重复 在单线程环境中,我只是基于种子创建random,并将其用于每次计算: Random random = new Random(37); for (Calculation c : calculations) { c.doCalculation(r.nextInt()); } 在多线程环境中,我有10个线程,我会有一个种子随机种子线程随机的: Random initRandom = new Random(37); for (

我需要做
1000
计算,每一个都基于一个随机数。 整个运行需要可重复

在单线程环境中,我只是基于种子创建random,并将其用于每次计算:

Random random = new Random(37);
for (Calculation c : calculations) {
    c.doCalculation(r.nextInt());
}
在多线程环境中,我有
10个
线程,我会有一个种子随机种子线程随机的:

Random initRandom = new Random(37);
for (List<Calculation> p : calculationPartitions) {
    final Random threadRandom = new Random(initRandom.nextLong());
    executorService.submit(() -> {
        for (Calculation c : p) {
            c.doCalculation(threadRandom.nextInt());
        }
    });
}
// Merge the calculation results back in the same order as the calculationPartitions
...
Random initRandom=new Random(37);
对于(列表p:计算分区){
final Random threadRandom=新随机数(initRandom.nextLong());
executorService.submit(()->{
用于(计算c:p){
c、 doCalculation(threadRandom.nextInt());
}
});
}
//将计算结果按与calculationPartitions相同的顺序合并回来
...
这是个好主意吗?总体上还是均匀分布的随机数?每个
threadRandom
都是由
initRandom
播种的,这一事实是否打破了均匀分布


出于可复制的原因,我无法共享1个全局随机数,因为某些线程在某些运行中可能比其他线程运行得更快,因此它们不会总是以相同的顺序调用全局随机数(争用可能会导致性能下降)。

通过随机数,您将获得均匀的数字分布,但是,无法保证列表中每个计算对象列表的运行顺序,因此,如果这些对象将结果传递到共享列表,则运行顺序可能会有所不同。

特别是关于均匀分布,每10个像素有一个随机位置似乎是可以的:

哦,等等,每1像素有1个随机位置,种子线程方法似乎更好!?在一个完美的均匀分布(尺寸250000)中,它将是全黑的:

左:

公共类SingleRandomProof扩展JFrame{
公共静态最终整数宽度=500;
公共静态最终内部高度=500;
公共静态最终整数大小=宽度*高度;
公共静态void main(字符串[]args){
SingleRandomProof=新的SingleRandomProof();
proof.pack();
证明。设置可见(真实);
proof.doCalc();
}
私人JLabel小组;
public SingleRandomProof()抛出HeadlessException{
超级(“1随机”);
BuffereImage=新的BuffereImage(宽度、高度、BuffereImage.TYPE_INT_ARGB);
面板=新JLabel(新图像图标(图像));
设置内容窗格(面板);
}
私有void doCalc(){
BuffereImage=新的BuffereImage(宽度、高度、BuffereImage.TYPE_INT_ARGB);
Graphics g=image.getGraphics();
g、 setColor(Color.WHITE);
g、 fillRect(0,0,宽度,高度);
g、 设置颜色(颜色为黑色);
随机r=新随机(37);
对于(int i=0;i
对:

public class SeededThreadRandomProof extends JFrame {

    public static final int WIDTH = 500;
    public static final int HEIGHT = 500;
    public static final int SIZE = WIDTH * HEIGHT;

    public static void main(String[] args) {
        SeededThreadRandomProof proof = new SeededThreadRandomProof();
        proof.pack();
        proof.setVisible(true);
        proof.doCalc();
    }

    private JLabel panel;

    public SeededThreadRandomProof() throws HeadlessException {
        super("10 seeded randoms");
        BufferedImage image = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_ARGB);
        panel = new JLabel(new ImageIcon(image));
        setContentPane(panel);
    }

    private void doCalc() {
        BufferedImage image = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_ARGB);
        Graphics g = image.getGraphics();
        g.setColor(Color.WHITE);
        g.fillRect(0, 0, WIDTH, HEIGHT);
        g.setColor(Color.BLACK);
        Random initRandom = new Random(37);
        for (int j = 0; j < 10; j++) {
            Random r = new Random(initRandom.nextLong());
            for (int i = 0; i < SIZE / 10; i++) {
                int position = r.nextInt(SIZE);
                g.fillRect(position % HEIGHT, position / HEIGHT, 1, 1);
            }
        }
        panel.setIcon(new ImageIcon(image));
    }

}
公共类seedThreadRandomProof扩展JFrame{
公共静态最终整数宽度=500;
公共静态最终内部高度=500;
公共静态最终整数大小=宽度*高度;
公共静态void main(字符串[]args){
seedThreadRandomProof=新的seedThreadRandomProof();
proof.pack();
证明。设置可见(真实);
proof.doCalc();
}
私人JLabel小组;
public seedThreadRandomProof()抛出HeadlessException{
超级(“10种子随机”);
BuffereImage=新的BuffereImage(宽度、高度、BuffereImage.TYPE_INT_ARGB);
面板=新JLabel(新图像图标(图像));
设置内容窗格(面板);
}
私有void doCalc(){
BuffereImage=新的BuffereImage(宽度、高度、BuffereImage.TYPE_INT_ARGB);
Graphics g=image.getGraphics();
g、 setColor(Color.WHITE);
g、 fillRect(0,0,宽度,高度);
g、 设置颜色(颜色为黑色);
随机初始随机=新随机(37);
对于(int j=0;j<10;j++){
Random r=新随机(initRandom.nextLong());
对于(int i=0;i
随机
生成均匀分布的数字,所以答案是:是的。这是一个合理的想法。如果共享一个随机数,则它们是同步的,这使得在不同线程中使用相同的随机数变得困难。您甚至可以使用除
列表
之外的其他内容,而是包含
列表
的自定义类,并且还包含
Random
@Andreas,因此线程都使用由原始随机数中的随机数作为种子的随机数这一事实不会破坏均匀分布保证?即随机数是以特定值(硬编码或其他地方)作为种子的事实,从那时起,Random将生成均匀分布的数字,这一事实不会改变。如果种子随机数没有做到这一点,你甚至无法在单线程环境中实现这一点,现在可以吗?Geoffrey,请查看并在其中进行讨论,它可能会给你一些见解…列表保留顺序,为什么您认为它们的顺序没有得到保证?Executor服务无法保证提交的Runnable将以什么顺序运行。因为它们是独立运行的线程?当然当他们只是在某处“发布”他们的结果时,结果集中的顺序可以完全。。。随机的。我第一次没有很好地解析你的句子。您的编辑有助于使其更加清晰。当然,执行顺序可以更改,但是与特定计算关联的
随机
不会更改
public class SeededThreadRandomProof extends JFrame {

    public static final int WIDTH = 500;
    public static final int HEIGHT = 500;
    public static final int SIZE = WIDTH * HEIGHT;

    public static void main(String[] args) {
        SeededThreadRandomProof proof = new SeededThreadRandomProof();
        proof.pack();
        proof.setVisible(true);
        proof.doCalc();
    }

    private JLabel panel;

    public SeededThreadRandomProof() throws HeadlessException {
        super("10 seeded randoms");
        BufferedImage image = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_ARGB);
        panel = new JLabel(new ImageIcon(image));
        setContentPane(panel);
    }

    private void doCalc() {
        BufferedImage image = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_ARGB);
        Graphics g = image.getGraphics();
        g.setColor(Color.WHITE);
        g.fillRect(0, 0, WIDTH, HEIGHT);
        g.setColor(Color.BLACK);
        Random initRandom = new Random(37);
        for (int j = 0; j < 10; j++) {
            Random r = new Random(initRandom.nextLong());
            for (int i = 0; i < SIZE / 10; i++) {
                int position = r.nextInt(SIZE);
                g.fillRect(position % HEIGHT, position / HEIGHT, 1, 1);
            }
        }
        panel.setIcon(new ImageIcon(image));
    }

}