gpt4 book ai didi

java - 使用多线程进行硬币翻转

转载 作者:行者123 更新时间:2023-12-02 05:15:19 30 4
gpt4 key购买 nike

我正在编写一个程序:“使用线程翻转硬币”。每个线程都在翻转硬币,如果翻转头部线程停止,如果翻转尾部,线程应该翻转直到你得到头部,然后停止该线程,最后每个线程计算我在行中翻转了多少尾部并将其作为数字。

这就是我所做的:

        import java.util.Scanner;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadLocalRandom;

/**
*
* @author jakub ozorowski
*/
final class RzutMoneta {
public static Float p;

public static void main(String... argv) {


System.out.print("Ilość wątków: ");
int ilość;
Scanner in = new Scanner(System.in);
ilość = in.nextInt();
System.out.print("Prawdopodobieństwo reszki: ");
p = in.nextFloat();

ExecutorService watki = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
for (int i = 0; i < ilość; ++i)
watki.submit(RzutMoneta::run); // wyskakuje w eclipse java problem????? w netbeansie działa bez problemu
watki.shutdown();
}

private static void run() {
Moneta moneta = new Moneta();
int count = 0;
while (moneta.rzut() == Moneta.Strony.Reszka) {
System.out.println(Thread.currentThread().getName() + ": reszka!");
++count;
}
System.out.printf("%s: orzel! %d reszka%n", Thread.currentThread().getName(), count);
}

}

final class Moneta {
public static double p;

Moneta() {
Moneta.p = RzutMoneta.p;
}

enum Strony {
Orzeł, Reszka
}

Strony rzut() {

//return ThreadLocalRandom.current().nextBoolean() ? Strony.Orzeł : Strony.Reszka;
return ThreadLocalRandom.current().nextFloat() > p ? Strony.Orzeł : Strony.Reszka;
}

}

my output:

Number of threads: 3
tails chance: 0,5
pool-1-thread-2: heads! 0 tails
pool-1-thread-3: tails!
pool-1-thread-1: heads! 0 tails
pool-1-thread-3: tails!
pool-1-thread-3: tails!
pool-1-thread-3: heads! 3 tails

//编辑工作程序。

最佳答案

如果我正确理解了这个问题,您将面临的一个障碍是您的所有线程都使用单个对象来跟踪硬币翻转(Rzut_Moneta 实例test ),但您希望每个线程打印翻转的尾部数量。如何将一个线程的结果与其他线程的结果分开?似乎每个线程都应该维护自己的计数器。

为了不断翻转尾部,你需要一个循环。像这样的事情:

while (flip() == Reszka) {
++count;
System.out.println("Tails! Flip again.");
}
System.out.println("Heads!");

看来您在变量作用域方面也遇到了麻烦。您已将所有变量声明为对象中的字段,但其中大多数应该是方法内部的局部变量。我认为不需要任何字段。

如果您需要在线程之间共享数据,您的 Rzut_Moneta 类就不安全;它没有内存屏障,因此不能保证每个线程的更改都是可见的。例如,如果您想计算所有线程看到的尾部总数,则需要将该计数器声明为 volatile ,或者只能在 同步 block 中访问,或者是特殊类型,例如 AtomicInteger .

如果每个线程都有自己的私有(private)计数器,则无需担心这些并发问题。

我建议这样的结构(只是一个草图,您必须填写原始代码中的详细信息):

import java.util.Scanner;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadLocalRandom;

final class RzutMoneta {

public static void main(String... argv) {
int ilość;
double headProbability;
try (Scanner input = new Scanner(System.in)) {
System.out.print("Number of threads: ");
ilość = input.nextInt();
System.out.print("Chance of heads: ");
headProbability = input.nextDouble();
}
ExecutorService threads = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
for (int i = 0; i < ilość; ++i)
threads.submit(() -> run(headProbability));
threads.shutdown();
}

private static void run(double headProbability) {
Moneta moneta = new Moneta(headProbability);
int count = 0;
while (moneta.rzut() == Moneta.Stroną.Reszka) {
System.out.println(Thread.currentThread().getName() + ": tails!");
++count;
}
System.out.printf("%s: heads! %d tails%n", Thread.currentThread().getName(), count);
}

}

final class Moneta {

enum Stroną {
Orzeł, Reszka
}

private final double headProbability;

Moneta() {
this(0.5);
}

Moneta(double headProbability) {
if ((headProbability < 0) || (headProbability > 1))
throw new IllegalArgumentException("Probability between 0.0 and 1.0");
this.headProbability = headProbability;
}

Stroną rzut() {
double toss = ThreadLocalRandom.current().nextDouble();
return (toss < headProbability) ? Stroną.Orzeł : Stroną.Reszka;
}

}

关于java - 使用多线程进行硬币翻转,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27006192/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com