编写使用线程来计算忽略操作顺序的表达式的Java程序?

问题描述 投票:-1回答:1

我正在尝试编写一个使用线程来计算表达式的Java程序,例如:

3 + 4 / 7 + 4 * 2

和输出

Enter problem: 3 + 4 / 7 + 4 * 2
Thread-0 calculated 3+4 as 7
Thread-1 calculated 7/7 as 1
Thread-2 calculated 1+4 as 5
Thread-3 calculated 5*2 as 10
Final result: 10

在此练习中,我们忽略了操作顺序。通过用户输入输入表达式。目标是获得一个单独的线程来执行每个计算。我绝对希望每个线程都执行每个单独的计算,如上所述。

这是我到目前为止编写的代码:

import java.util.Scanner;

class math2 extends Thread {    
    public void run() {
        //Initialize variable that will be the result printed in the end
        int result = 0;

        //Gather user input
        System.out.print("Enter equation: ");
        Scanner console = new Scanner(System.in);
        String eqn = console.nextLine();

        //Tokens are delimited by a space
        String[] tokens = eqn.split(" ");

        //For each token in the array, we will do a calculation.
        for (int i = 0; i < tokens.length; i += 2) {
            for (int j = 0; j < tokens.length - 1; j += 2) {
                //Parse user input through the switch/break loop
                switch (tokens[j].charAt(0)) {
                case '+': 
                    result = Integer.parseInt(tokens[i]) + Integer.parseInt(tokens[i + 1]);
                    break;
                case '-':
                    result = Integer.parseInt(tokens[i]) - Integer.parseInt(tokens[i + 1]);
                    break;
                case '*':
                    result = Integer.parseInt(tokens[i]) * Integer.parseInt(tokens[i + 1]);
                    break;
                case '/':
                    result = Integer.parseInt(tokens[i]) / Integer.parseInt(tokens[i + 1]);
                    break;
                default: 
                    System.out.println("Invalid input. Please try again.");
                    break;
                }
            }
        }
        System.out.println("Final result: " + result);
    }

    public static void main(String[] args) {
        math2 t1 = new math2();

        t1.start();

        try {
            System.out.println("Thread ID calculated " + t1.getName());
            t1.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

如何设置工作,以便线程可以计算问题的每个部分?我应该将代码的用户输入部分(扫描仪对象)移到main方法吗?预先谢谢你。

更新:根据收到的建议,我尝试了以下操作-但我仍然不明白如何获取这些线程以返回表达式前一部分的值?如何(并且应该?)创建多个线程来完成此任务?

import java.util.Scanner;

class Main extends Thread { 
  //Initialize variable that will be the result printed in the end
    private volatile int result = 0;

    public void run() {
      result = evaluate(x, y, sign);
    }

  public int getResult() {
    return result;
  }

  public int evaluate(int x, int y, char sign) {
    switch (sign) {
        case '+': 
          z = x + y;
          break;
        case '-':
          z = x - y;
          break;
        case '*':
          z = x * y;
          break;
        case '/':
          z = x / y;
          break;
        default: 
          System.out.println("Invalid input. Please try again.");
          break;
        }
    return z;
  }

    public static void main(String[] args) {
      //Gather user input
      System.out.print("Enter equation: ");
      Scanner console = new Scanner(System.in);
      String eqn = console.nextLine();

      //Tokens are delimited by a space
      String[] tokens = eqn.split(" ");
        Main t1 = new Main();

        try {
      t1.start();
            System.out.println("Thread ID calculated " + t1.getName());
            t1.join();
      result = t1.getResult();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
java operating-system switch-statement java-threads
1个回答
0
投票

我诚实,专业的建议是不要尝试使用多线程解决此问题。

首先学习编写清晰,健壮的单线程代码。了解如何调试它。学习如何以许多不同的方式来写同一件事。只有到那时,您才可以开始介绍多线程的enormous复杂性,并有可能保证它是正确的。

并且通过阅读多线程代码来学习哪些问题将从多线程中受益。不会出现此问题,因为您需要前一个算术运算的结果作为下一个运算的输入。

我之所以回答,是因为在使用全局变量的注释中提供了可怕的建议。 不要。即使在这样一个简单的示例中,这也不是编写多线程代码的好方法。即使在单线程代码中,也应该避免使用可变的全局状态。

请尽可能严格控制您的可变状态。创建一个Runnable子类,其中包含要执行的操作:

class Op implements Runnable {
  final int operand1, operand2;
  final char oprator;

  int result;

  Op(int operand1, char oprator, int operand2) {
    // Initialize fields.
  }

  @Override public void run() {
    result = /* code to calculate `operand1 (oprator) operand2` */;
  }
}

现在,您可以使用以下方法来计算1 + 2

Op op = new Op(1, '+', 2);
Thread t = new Thread(op);
t.start();
t.join();
int result = op.result;

(或者,您本可以使用int result = 1 + 2; ...]

所以您现在可以在循环中使用它:

String[] tokens = eqn.split(" ");
int result = Integer.parseInt(tokens[0]);
for (int t = 1; t < tokens.length; t += 2) {
  Op op = new Op(
      result,
      result, tokens[t].charAt(0), 
      Integer.parseInt(tokens[t+1]));
  Thread t = new Thread(op);
  t.start();
  t.join();    
  result = op.result;
}

所有可变状态都限于op变量的范围。例如,如果您想进行第二次计算,则不必担心以前的状态仍然存在:不必在再次运行之前重设任何内容。您可以根据需要并行调用此代码,而不会在运行之间产生干扰。

© www.soinside.com 2019 - 2024. All rights reserved.