命令行终端在进程上执行并从此进程输入交互
Command line terminal executing on process and input interaction from this process
基本上,当我按下 java 应用程序上的按钮时,我有一个运行的进程。
而这个进程向OS的终端执行命令。
但有时此命令需要与用户进行交互。
我想知道是否可以在需要时让流程与用户进行交互?
我的代码:
File marsSimulator = new File("resources/mars_simulator/Mars4_5.jar");
if(marsSimulator.exists() && temp.exists()){
String res="";
try {
Process p = Runtime.getRuntime().exec(new String[]{"java","-jar",marsSimulator.getAbsolutePath(),tempAssembly.getAbsolutePath()});
p.waitFor();
InputStream is = p.getInputStream();
byte b[] = new byte[is.available()];
is.read(b, 0, b.length); // probably try b.length-1 or -2 to remove "new-line(s)"
res = new String(b);
} catch (Exception ex) {
ex.printStackTrace();
}
}
此外,我忘了说该应用程序是使用 SWING 制作的,并且该过程的输出显示在 TextArea 上...我应该更改任何内容吗?
请注意,当与用户进行交互时,进程会阻塞。如果没有,进程不会阻塞!
在这种情况下我需要做什么(我不知道该怎么做)?
- 进程需要交互时。我需要知道进程何时需要一些交互。
- 我需要以交互方式(逐行)获取流程生成的输出。
P.S.: 对于想了解流程线的人,我正在使用火星模拟器 (http://courses.missouristate.edu/KenVollmar/MARS/) 并将 jar 应用程序发送到一个带有 mips 汇编代码的进程中.
下一段代码正在与我的项目一起使用
希望对以后的冒险家有所帮助!
感谢 Nicolas Filotto 对我的帮助。
我的 class ObservableStream:
class ObservableStream extends Observable {
private final Queue<String> lines = new ConcurrentLinkedQueue<>();
public void addLine(String line) {
lines.add(line);
setChanged();
notifyObservers();
}
public String nextLine() {
return lines.poll();
}
public String getLine(){return lines.peek();}
}
以及代码的另一部分:
Process p = Runtime.getRuntime().exec(new String[]{"java","-jar",marsSimulator.getAbsolutePath(),tempAssembly.getAbsolutePath()});
//This code does the interaction from the process with the GUI ! Implied, input interaction+output interaction from the process
ObservableStream out = new ObservableStream();
// Observer that simply sends to my external process line by line what we put in
// the variable output
PrintWriter writer = new PrintWriter(p.getOutputStream(), true);
out.addObserver(
(o, arg) -> {
ObservableStream stream = (ObservableStream) o;
String line;
while ((line = stream.nextLine()) != null) {
writer.println(line);
}
}
);
ObservableStream input = new ObservableStream();
input.addObserver(
(o, arg) -> {
ObservableStream stream = (ObservableStream) o;
String line;
while ((line = stream.nextLine()) != null) {
outputTextArea.appendText(line+"\n");
}
}
);
// The thread that reads the standard output stream of the external process
// and put the lines into my variable input
new Thread(
() -> {
try (BufferedReader reader = new BufferedReader(
new InputStreamReader(p.getInputStream()))
) {
String line;
while ((line = reader.readLine()) != null) {
input.addLine(line);
}
} catch (IOException e1) {
e1.printStackTrace();
}
}
).start();
new Thread(
()->{
while(p.isAlive()){
String res = input.getLine();
if(res!=null && res.equals("Enter integer value:")) {
boolean integerIsRequested=true;
Thread t=null;
while(integerIsRequested){
if(t==null) {
t = new Thread(new Runnable() {
public void run() {
String test1 = JOptionPane.showInputDialog("Enter Integer value:");
while(!test1.matches("^\d+$")){
test1 = JOptionPane.showInputDialog("Error: Not a valid Integer.\nEnter a correct Integer value:");
}
Integer i = Integer.valueOf(test1);
if (i != null) {
out.addLine(test1);
}
}
});
t.start();
}
if(!t.isAlive()){
integerIsRequested=false;
}
}
}
}
outputTextArea.appendText("Program executed\n");
}
).start();
顺便说一下,这个 post 是独一无二的 Jarrod ;)
我认为您无法从 Java 检查进程的状态。但是,您可以使用一些 Linux 命令来完成。 (当然,如果你使用 Linux)
如果您的 Java 进程可以访问 /proc
目录,那么您可以读取该进程的 status
文件。
例如,进程 ID 为 12280
的进程
/proc/12280/status
这是 status
文件的相关输出
Name: java
State: S (sleeping)
Tgid: 12280
Pid: 12280
PPid: 12279
...
第二行给出进程的状态。您需要 运行 一个线程来连续轮询此文件以读取状态。
我希望它能回答您的问题... subProcessStuff
"emulates" 该子流程。它可以是任何东西——但这样我们就万事俱备了。它需要 2 个参数传递到控制台。字符串和整数。 Gobbler
得到 Callback
这是一个接口,具有匿名实现 - 并且有参数检查。要回答子进程是否等待,我们只需跟踪所说的内容 - 就像用户是否会使用它一样。
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintStream;
import java.util.Scanner;
class Test1 {
public static void main(String[] args) {
for (String arg : args)
System.out.println("arg: " + arg);
for (String arg : args)
if (arg.equals("-test")) {
subProcessStuff();
return;
}
mainProcess();
}
public static void subProcessStuff() {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
try {
System.out.println("Enter String");
String s = br.readLine();
System.out.println("Enered String: " + s);
System.out.println("Enter Integer:");
int i = Integer.parseInt(br.readLine());
System.out.println("Entered Integer: " + i);
} catch (IOException e) {
System.err.println("io error - " + e.getMessage());
} catch (NumberFormatException nfe) {
System.err.println("Invalid Format!");
}
}
private static PrintStream out;
public static void mainProcess() {
String[] commands = { "ls", "-alt" };
ProcessBuilder builder = new ProcessBuilder("java", "Test1", "-test");
// builder.inheritIO(); // I avoid this. It was messing me up.
try {
Process proc = builder.start();
InputStream errStream = proc.getErrorStream();
InputStream inStream = proc.getInputStream();
OutputStream outStream = proc.getOutputStream();
new Thread(new StreamGobbler("err", out, errStream)).start();
out = new PrintStream(new BufferedOutputStream(outStream));
Callback cb = new Callback() {
@Override
public void onNextLine(String line) {
if (line.equals("Enter String")) {
out.println("aaaaa");
out.flush();
}
if (line.equals("Enter Integer:")) {
out.println("123");
out.flush();
}
}
};
new Thread(new StreamGobbler("in", out, inStream, cb)).start();
int errorCode = proc.waitFor();
System.out.println("error code: " + errorCode);
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
if (out != null) {
out.close();
}
}
}
}
interface Callback {
void onNextLine(String line);
}
class StreamGobbler implements Runnable {
private PrintStream out;
private Scanner inScanner;
private String name;
private Callback cb;
public StreamGobbler(String name, PrintStream out, InputStream inStream) {
this.name = name;
this.out = out;
inScanner = new Scanner(new BufferedInputStream(inStream));
}
public StreamGobbler(String name, PrintStream out, InputStream inStream, Callback cb) {
this.name = name;
this.out = out;
inScanner = new Scanner(new BufferedInputStream(inStream));
this.cb = cb;
}
@Override
public void run() {
while (inScanner.hasNextLine()) {
String line = inScanner.nextLine();
if (cb != null)
cb.onNextLine(line);
System.out.printf("%s: %s%n", name, line);
}
}
}
为了实现这样的用例,我个人会使用:
- 一个
Observable
对象,用于在外部进程提供新行时通知我的 UI
- 一个
Observable
对象,我向其添加由 UI 提供的新行
- #1 的
Observer
将刷新我的 UI 的数据
- #2 的
Observer
会将我的 UI 提供的行发送到我的外部进程
- A
Thread
将检查我的外部进程是否提供了新行,如果是,它会将这些行提供给 #1
因为我没有你的完整环境,我将向你展示它如何与模拟对象一起工作:
首先是我的伪造外部应用程序,它只对他收到的内容执行 Echo
:
public class Echo {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
while (true) {
String line = scanner.nextLine();
System.out.printf("echo > %s%n", line);
}
}
}
如果这个class接收到foo
,它会打印到标准输出流echo > foo
然后我的Observable
class
public class ObservableStream extends Observable {
private final Queue<String> lines = new ConcurrentLinkedQueue<>();
public void addLine(String line) {
lines.add(line);
setChanged();
notifyObservers();
}
public String nextLine() {
return lines.poll();
}
}
注意: class ObservableStream
(到目前为止已经实现)意味着只有一个 Observer
没有更多根据您的需要就足够了。 Indeed 仅用于将您的 UI 与数据的检索或发布方式分离
最后是主要代码:
Process p = Runtime.getRuntime().exec(
new String[]{"java", "-cp", "/my/path/to/my/classes", "Echo"}
);
// The Observable object allowing to get the input lines from my external process
ObservableStream input = new ObservableStream();
// A mock observer that simply prints the lines provided by the external process
// but in your case you will update your text area instead
input.addObserver(
(o, arg) -> {
ObservableStream stream = (ObservableStream) o;
String line;
while ((line = stream.nextLine()) != null) {
System.out.printf("Line Received from the external process: %s%n", line);
}
}
);
// The thread that reads the standard output stream of the external process
// and put the lines into my variable input
new Thread(
() -> {
try (BufferedReader reader = new BufferedReader(
new InputStreamReader(p.getInputStream()))
) {
String line;
while ((line = reader.readLine()) != null) {
input.addLine(line);
}
} catch (IOException e) {
e.printStackTrace();
}
}
).start();
// The Observable object allowing to send the input lines to my external process
ObservableStream output = new ObservableStream();
// Observer that simply sends to my external process line by line what we put in
// the variable output
PrintWriter writer = new PrintWriter(p.getOutputStream(), true);
output.addObserver(
(o, arg) -> {
ObservableStream stream = (ObservableStream) o;
String line;
while ((line = stream.nextLine()) != null) {
writer.println(line);
}
}
);
// A simple scanner used to send new messages to my external process
Scanner scanner = new Scanner(System.in);
while (true) {
output.addLine(scanner.nextLine());
}
如果这段代码接收到foo
,它会打印到标准输出流Line Received from the external process: echo > foo
逐行代码我用来与不同的 jar 交互,speechRecognizer.I 认为你想要实现这样的目标。
示例:
我正在交互的 jar(speechRecognizer) 正在执行不同的命令和 运行 一些其他 Threads.Every 时间它必须与主 jar 交互它打印一些我 need.For 示例(用户 said:How 是你),所以你可以有相同的逻辑,当外部 jar 需要与用户交互时,它会打印一些东西,然后你将它读入主 app.So:
// About Process
private Process process;
private BufferedReader bufferedReader;
private boolean stopped = true;
Thread processChecker;
//Running it in a Thread so the app don't lags
new Thread(() -> {
try {
stopped = false;
//Starting the external jar..
ProcessBuilder builder = new ProcessBuilder("java", "-jar", System.getProperty("user.home")
+ File.separator + "Desktop" + File.separator + "speechRecognizer.jar", "BITCH_PLEASE");
//Redirecting the ErrorStream
builder.redirectErrorStream(true);
process = builder.start();
bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line;
//Check continusly if the process is still alive
//i case of crash i should do something..
processChecker = new Thread(() -> {
while (process.isAlive()) {
try {
Thread.sleep(1200);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
stopSpeechReader(false);
});
processChecker.start();
// Continuesly Read Output of external process
while (!stopped) {
while ((line = bufferedReader.readLine()) != null && !line.isEmpty()) {
System.out.println(line);
checkSpeechResult(line);
}
}
// Interrupt the mf Thread if is Alive
if (processChecker.isAlive())
processChecker.interrupt();
System.out.println("SpeechReader Stopped! Process is alive:" + process.isAlive() + " >Exit Value:"
+ process.exitValue());
} catch (Exception e) {
e.printStackTrace();
}
}).start();
基本上,当我按下 java 应用程序上的按钮时,我有一个运行的进程。 而这个进程向OS的终端执行命令。 但有时此命令需要与用户进行交互。 我想知道是否可以在需要时让流程与用户进行交互?
我的代码:
File marsSimulator = new File("resources/mars_simulator/Mars4_5.jar");
if(marsSimulator.exists() && temp.exists()){
String res="";
try {
Process p = Runtime.getRuntime().exec(new String[]{"java","-jar",marsSimulator.getAbsolutePath(),tempAssembly.getAbsolutePath()});
p.waitFor();
InputStream is = p.getInputStream();
byte b[] = new byte[is.available()];
is.read(b, 0, b.length); // probably try b.length-1 or -2 to remove "new-line(s)"
res = new String(b);
} catch (Exception ex) {
ex.printStackTrace();
}
}
此外,我忘了说该应用程序是使用 SWING 制作的,并且该过程的输出显示在 TextArea 上...我应该更改任何内容吗?
请注意,当与用户进行交互时,进程会阻塞。如果没有,进程不会阻塞!
在这种情况下我需要做什么(我不知道该怎么做)?
- 进程需要交互时。我需要知道进程何时需要一些交互。
- 我需要以交互方式(逐行)获取流程生成的输出。
P.S.: 对于想了解流程线的人,我正在使用火星模拟器 (http://courses.missouristate.edu/KenVollmar/MARS/) 并将 jar 应用程序发送到一个带有 mips 汇编代码的进程中.
下一段代码正在与我的项目一起使用
希望对以后的冒险家有所帮助!
感谢 Nicolas Filotto 对我的帮助。
我的 class ObservableStream:
class ObservableStream extends Observable {
private final Queue<String> lines = new ConcurrentLinkedQueue<>();
public void addLine(String line) {
lines.add(line);
setChanged();
notifyObservers();
}
public String nextLine() {
return lines.poll();
}
public String getLine(){return lines.peek();}
}
以及代码的另一部分:
Process p = Runtime.getRuntime().exec(new String[]{"java","-jar",marsSimulator.getAbsolutePath(),tempAssembly.getAbsolutePath()});
//This code does the interaction from the process with the GUI ! Implied, input interaction+output interaction from the process
ObservableStream out = new ObservableStream();
// Observer that simply sends to my external process line by line what we put in
// the variable output
PrintWriter writer = new PrintWriter(p.getOutputStream(), true);
out.addObserver(
(o, arg) -> {
ObservableStream stream = (ObservableStream) o;
String line;
while ((line = stream.nextLine()) != null) {
writer.println(line);
}
}
);
ObservableStream input = new ObservableStream();
input.addObserver(
(o, arg) -> {
ObservableStream stream = (ObservableStream) o;
String line;
while ((line = stream.nextLine()) != null) {
outputTextArea.appendText(line+"\n");
}
}
);
// The thread that reads the standard output stream of the external process
// and put the lines into my variable input
new Thread(
() -> {
try (BufferedReader reader = new BufferedReader(
new InputStreamReader(p.getInputStream()))
) {
String line;
while ((line = reader.readLine()) != null) {
input.addLine(line);
}
} catch (IOException e1) {
e1.printStackTrace();
}
}
).start();
new Thread(
()->{
while(p.isAlive()){
String res = input.getLine();
if(res!=null && res.equals("Enter integer value:")) {
boolean integerIsRequested=true;
Thread t=null;
while(integerIsRequested){
if(t==null) {
t = new Thread(new Runnable() {
public void run() {
String test1 = JOptionPane.showInputDialog("Enter Integer value:");
while(!test1.matches("^\d+$")){
test1 = JOptionPane.showInputDialog("Error: Not a valid Integer.\nEnter a correct Integer value:");
}
Integer i = Integer.valueOf(test1);
if (i != null) {
out.addLine(test1);
}
}
});
t.start();
}
if(!t.isAlive()){
integerIsRequested=false;
}
}
}
}
outputTextArea.appendText("Program executed\n");
}
).start();
顺便说一下,这个 post 是独一无二的 Jarrod ;)
我认为您无法从 Java 检查进程的状态。但是,您可以使用一些 Linux 命令来完成。 (当然,如果你使用 Linux)
如果您的 Java 进程可以访问 /proc
目录,那么您可以读取该进程的 status
文件。
例如,进程 ID 为 12280
/proc/12280/status
这是 status
文件的相关输出
Name: java
State: S (sleeping)
Tgid: 12280
Pid: 12280
PPid: 12279
...
第二行给出进程的状态。您需要 运行 一个线程来连续轮询此文件以读取状态。
我希望它能回答您的问题... subProcessStuff
"emulates" 该子流程。它可以是任何东西——但这样我们就万事俱备了。它需要 2 个参数传递到控制台。字符串和整数。 Gobbler
得到 Callback
这是一个接口,具有匿名实现 - 并且有参数检查。要回答子进程是否等待,我们只需跟踪所说的内容 - 就像用户是否会使用它一样。
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintStream;
import java.util.Scanner;
class Test1 {
public static void main(String[] args) {
for (String arg : args)
System.out.println("arg: " + arg);
for (String arg : args)
if (arg.equals("-test")) {
subProcessStuff();
return;
}
mainProcess();
}
public static void subProcessStuff() {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
try {
System.out.println("Enter String");
String s = br.readLine();
System.out.println("Enered String: " + s);
System.out.println("Enter Integer:");
int i = Integer.parseInt(br.readLine());
System.out.println("Entered Integer: " + i);
} catch (IOException e) {
System.err.println("io error - " + e.getMessage());
} catch (NumberFormatException nfe) {
System.err.println("Invalid Format!");
}
}
private static PrintStream out;
public static void mainProcess() {
String[] commands = { "ls", "-alt" };
ProcessBuilder builder = new ProcessBuilder("java", "Test1", "-test");
// builder.inheritIO(); // I avoid this. It was messing me up.
try {
Process proc = builder.start();
InputStream errStream = proc.getErrorStream();
InputStream inStream = proc.getInputStream();
OutputStream outStream = proc.getOutputStream();
new Thread(new StreamGobbler("err", out, errStream)).start();
out = new PrintStream(new BufferedOutputStream(outStream));
Callback cb = new Callback() {
@Override
public void onNextLine(String line) {
if (line.equals("Enter String")) {
out.println("aaaaa");
out.flush();
}
if (line.equals("Enter Integer:")) {
out.println("123");
out.flush();
}
}
};
new Thread(new StreamGobbler("in", out, inStream, cb)).start();
int errorCode = proc.waitFor();
System.out.println("error code: " + errorCode);
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
if (out != null) {
out.close();
}
}
}
}
interface Callback {
void onNextLine(String line);
}
class StreamGobbler implements Runnable {
private PrintStream out;
private Scanner inScanner;
private String name;
private Callback cb;
public StreamGobbler(String name, PrintStream out, InputStream inStream) {
this.name = name;
this.out = out;
inScanner = new Scanner(new BufferedInputStream(inStream));
}
public StreamGobbler(String name, PrintStream out, InputStream inStream, Callback cb) {
this.name = name;
this.out = out;
inScanner = new Scanner(new BufferedInputStream(inStream));
this.cb = cb;
}
@Override
public void run() {
while (inScanner.hasNextLine()) {
String line = inScanner.nextLine();
if (cb != null)
cb.onNextLine(line);
System.out.printf("%s: %s%n", name, line);
}
}
}
为了实现这样的用例,我个人会使用:
- 一个
Observable
对象,用于在外部进程提供新行时通知我的 UI - 一个
Observable
对象,我向其添加由 UI 提供的新行
- #1 的
Observer
将刷新我的 UI 的数据
- #2 的
Observer
会将我的 UI 提供的行发送到我的外部进程 - A
Thread
将检查我的外部进程是否提供了新行,如果是,它会将这些行提供给 #1
因为我没有你的完整环境,我将向你展示它如何与模拟对象一起工作:
首先是我的伪造外部应用程序,它只对他收到的内容执行 Echo
:
public class Echo {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
while (true) {
String line = scanner.nextLine();
System.out.printf("echo > %s%n", line);
}
}
}
如果这个class接收到foo
,它会打印到标准输出流echo > foo
然后我的Observable
class
public class ObservableStream extends Observable {
private final Queue<String> lines = new ConcurrentLinkedQueue<>();
public void addLine(String line) {
lines.add(line);
setChanged();
notifyObservers();
}
public String nextLine() {
return lines.poll();
}
}
注意: class ObservableStream
(到目前为止已经实现)意味着只有一个 Observer
没有更多根据您的需要就足够了。 Indeed 仅用于将您的 UI 与数据的检索或发布方式分离
最后是主要代码:
Process p = Runtime.getRuntime().exec(
new String[]{"java", "-cp", "/my/path/to/my/classes", "Echo"}
);
// The Observable object allowing to get the input lines from my external process
ObservableStream input = new ObservableStream();
// A mock observer that simply prints the lines provided by the external process
// but in your case you will update your text area instead
input.addObserver(
(o, arg) -> {
ObservableStream stream = (ObservableStream) o;
String line;
while ((line = stream.nextLine()) != null) {
System.out.printf("Line Received from the external process: %s%n", line);
}
}
);
// The thread that reads the standard output stream of the external process
// and put the lines into my variable input
new Thread(
() -> {
try (BufferedReader reader = new BufferedReader(
new InputStreamReader(p.getInputStream()))
) {
String line;
while ((line = reader.readLine()) != null) {
input.addLine(line);
}
} catch (IOException e) {
e.printStackTrace();
}
}
).start();
// The Observable object allowing to send the input lines to my external process
ObservableStream output = new ObservableStream();
// Observer that simply sends to my external process line by line what we put in
// the variable output
PrintWriter writer = new PrintWriter(p.getOutputStream(), true);
output.addObserver(
(o, arg) -> {
ObservableStream stream = (ObservableStream) o;
String line;
while ((line = stream.nextLine()) != null) {
writer.println(line);
}
}
);
// A simple scanner used to send new messages to my external process
Scanner scanner = new Scanner(System.in);
while (true) {
output.addLine(scanner.nextLine());
}
如果这段代码接收到foo
,它会打印到标准输出流Line Received from the external process: echo > foo
逐行代码我用来与不同的 jar 交互,speechRecognizer.I 认为你想要实现这样的目标。
示例:
我正在交互的 jar(speechRecognizer) 正在执行不同的命令和 运行 一些其他 Threads.Every 时间它必须与主 jar 交互它打印一些我 need.For 示例(用户 said:How 是你),所以你可以有相同的逻辑,当外部 jar 需要与用户交互时,它会打印一些东西,然后你将它读入主 app.So:
// About Process
private Process process;
private BufferedReader bufferedReader;
private boolean stopped = true;
Thread processChecker;
//Running it in a Thread so the app don't lags
new Thread(() -> {
try {
stopped = false;
//Starting the external jar..
ProcessBuilder builder = new ProcessBuilder("java", "-jar", System.getProperty("user.home")
+ File.separator + "Desktop" + File.separator + "speechRecognizer.jar", "BITCH_PLEASE");
//Redirecting the ErrorStream
builder.redirectErrorStream(true);
process = builder.start();
bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line;
//Check continusly if the process is still alive
//i case of crash i should do something..
processChecker = new Thread(() -> {
while (process.isAlive()) {
try {
Thread.sleep(1200);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
stopSpeechReader(false);
});
processChecker.start();
// Continuesly Read Output of external process
while (!stopped) {
while ((line = bufferedReader.readLine()) != null && !line.isEmpty()) {
System.out.println(line);
checkSpeechResult(line);
}
}
// Interrupt the mf Thread if is Alive
if (processChecker.isAlive())
processChecker.interrupt();
System.out.println("SpeechReader Stopped! Process is alive:" + process.isAlive() + " >Exit Value:"
+ process.exitValue());
} catch (Exception e) {
e.printStackTrace();
}
}).start();