【问题标题】:Exact same code (with multithreading) doesn't work on 2 different computers完全相同的代码(使用多线程)在两台不同的计算机上不起作用
【发布时间】:2016-03-04 18:47:39
【问题描述】:

我目前正在开发一个简单的国际象棋人工智能。 (计算可能的未来转弯,给它们打分,选择最好的,+一些技巧,这样你就不必计算每一个转弯)。代码是用 Java 编写的,我使用的是 Netbeans。为了使计算更快,我使用多线程。代码大致是这样的:

  • Main 函数先进行一些计算,然后启动 8 个线程。
  • 线程执行主计算
  • 当他们完成时,他们在一个布尔数组 (finished[]) 中设置一个布尔值 true。这个数组在“主类”中(如果你这样称呼它),主函数也在其中。
  • 在这段时间内,主函数一直在等待并不断检查finished[] - 数组的每个值是否为真。如果是这种情况,它会继续工作。

现在我有一个奇怪的问题。该代码在我的 PC 上运行良好,但是当我在笔记本电脑上运行完全相同的代码时,main 函数将无法继续工作,毕竟 finished[]-array 的所有值都是 true。我已经对代码进行了一些更改,因此我可以尝试使用不同数量的线程,但结果始终相同。

我完全不知道这里发生了什么,如果你们中的任何人有任何答案和/或建议,我将不胜感激!

如果您需要更多信息,尽管问,我会尽力而为。 :)

(抱歉可能出现语法错误,英语不是我的母语,但我正在尽力而为。;))

所以我被要求展示一些我在程序中使用的代码:

(也许首先是一个警告,是的,我仍然是 Java 中的大菜鸟,这是我第一次使用线程,所以如果您看到我可能犯的严重错误,请不要感到震惊。xD)

主类看起来像这样:

public class Chess_ai_20 {

   static boolean finished[] = new boolean[8];
   Distributor[] Distributors = new Distributor[8];
   ...

   public static void main(String[] args) {
      boolean testing=false;
      ...
      //some calculations and other stuff
      ...
      Distributors[0] = new Distributor(...., "0"); //the String "0" will be the thread name.
      Distributors[1] = new ...
      ...
      Distributors[7] = new Distributor(...., "7");

      for (int i = 0; i < 8; i++) {
          Distributoren[i].start();
       }

       testing=false;

       while(testing==false){
          if(finished[0]==true && finished[1]==true && ... && finished[7]==true){
             testing=true;   //That's the point where I get stuck I suppose
           }
        }

        System.out.println("I made it!");
   }

   public static void setFinished(int i) {
      finished[i] = true;
      System.out.println("finished [" + i + "] = " + finished[i]);
      System.out.println(Arrays.toString(finished));   //To check how many values already are true
    }
 }

然后我们当然得到了“分销商”类

public class Distributor extends Thread {
   Thread t;
   String threadname;
   boolean running=false;
   ...
   Distributor(......, String s) {
      threadname=s;
      ...
      ...
   }

   @Override
   public void start() {
      running=true;
      if (t == null) {
          t = new Thread(this,threadname);
          t.start();
      }
    }

   @Override
   public void run() {
      if(running){
         ...
         //Do the main calculations etc.
         ...
         //All the Calculations habe been done at this point
         Chess_ai_20.setFinished(Character.getNumericValue(threadname.charAt(0))); //Set the value of finished[] true in the main class
         running=false;
      }
   }
}

【问题讨论】:

  • 您应该发布代码。根据您的描述,可能发生了竞态条件。
  • 您应该发布代码。我的猜测是对finished[]的访问没有正确同步。
  • @JoopEggen,与其加入八个线程,然后每次移动启动八个新线程,不如教菜鸟使用线程池。主程序可以提交八个任务,然后等待期货完成。它在国际象棋程序中可能没有任何区别,但它会在未来很好地服务于 OP,以养成池线程的习惯。
  • @jameslarge 感谢您的提示!是的,我是一个菜鸟,但我渴望增加我的知识。我会告诉自己有关线程池的信息。
  • @JoopEggen 感谢您的提示和链接。总是乐于学习新事物。 :)

标签: java multithreading


【解决方案1】:

正如其他人所提到的,使用Future 会更简单易懂。下面是一个演示如何重写代码的 sn-p。查看code in action

首先,您编写一个Callable 来定义您想要执行的任务。

public class MyCallable implements Callable<Boolean> {

    @Override
    public Boolean call() {
        // Do some job and return the result.
        return Boolean.TRUE;
    }
}

然后,您将此任务提交给Executor。 JDK中有很多Executor。你想先通过Concurrency Tutorial

    ExecutorService executor = Executors.newFixedThreadPool(Runtime
            .getRuntime().availableProcessors());
    List<Callable<Boolean>> callables = new ArrayList<>();
    for (int counter = 0; counter < 8; counter++) {
        callables.add(new MyCallable());
    }

    List<Future<Boolean>> futures = executor.invokeAll(callables);
    for (Future<Boolean> future : futures) {
        System.out.println(future.get()); // You'd want to store this into an array or wherever you see fit.
    }

    executor.shutdown();

记住futures returned by the executor are in the same order as the Callables you submitted (or added)Collection(在本例中为ArrayList)。因此,您无需担心返回索引、ID 甚至Thread 的名称(如果您分配了一个)来映射相应的结果。

【讨论】:

  • 非常感谢您提供的精彩教程和对其他文档的参考!我更改了我的代码,并将您提议的系统与线程池和期货联系起来。该代码现在可以在我的笔记本电脑和我的电脑上成功运行! :) 祝你有美好的一天,再次感谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-10
  • 2016-12-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多