我正在尝试编写一个使用线程来计算表达式的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();
}
}
}
我诚实,专业的建议是不要尝试使用多线程解决此问题。
首先学习编写清晰,健壮的单线程代码。了解如何调试它。学习如何以许多不同的方式来写同一件事。只有到那时,您才可以开始介绍多线程的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
变量的范围。例如,如果您想进行第二次计算,则不必担心以前的状态仍然存在:不必在再次运行之前重设任何内容。您可以根据需要并行调用此代码,而不会在运行之间产生干扰。