execute进程,无需jframe冻结

weylhg0b  于 2021-07-13  发布在  Java
关注(0)|答案(3)|浏览(396)

如何在java中执行进程而不冻结程序?我试过使用swingworker,但我还不太明白它是如何工作的。
我还有别的办法可以做到吗?我想在我的jdroidlib中使用这样的东西。有关完整的源代码,请查看github:http://github.com/team-m4gkbeatz/jdroidlib
提前谢谢!
编辑:
谢谢你的回答。但是我有一个有几个方法的类(好吧,它不止一个类,但是你明白我的意思);我怎么能用一个摇摆人来和他们互动呢?
以下是其中一个类:

  1. /**
  2. *
  3. * @author Simon
  4. */
  5. public abstract class Command extends SwingWorker {
  6. BufferedReader prReader = null;
  7. ProcessBuilder process = null;
  8. Process pr = null;
  9. Date timeNow = new Date();
  10. String osName = System.getProperty("os.name");
  11. public void executeProcessNoReturn(String _process, String arg) throws IOException {
  12. process = new ProcessBuilder(_process, arg);
  13. pr = process.start();
  14. }
  15. public String executeProcessReturnLastLine(String _process, String arg) throws IOException {
  16. process = new ProcessBuilder(_process, arg);
  17. pr = process.start();
  18. prReader = new BufferedReader(new InputStreamReader(pr.getInputStream()));
  19. String line;
  20. while ((line = prReader.readLine()) != null) {
  21. // Wait for input to end.
  22. }
  23. return line;
  24. }
  25. public StringBuilder executeProcessReturnAllOutput(String _process, String arg) throws IOException {
  26. process = new ProcessBuilder(_process, arg);
  27. pr = process.start();
  28. prReader = new BufferedReader(new InputStreamReader(pr.getInputStream()));
  29. StringBuilder output = null;
  30. String line;
  31. while ((line = prReader.readLine()) != null) {
  32. output.append(line);
  33. }
  34. return output;
  35. }
  36. public boolean isProcessRunning(String processName) throws IOException {
  37. boolean value = false;
  38. if (osName.equals("Linux") | osName.contains("Mac")) {
  39. process = new ProcessBuilder("ps", "-e");
  40. pr = process.start();
  41. String line;
  42. prReader = new BufferedReader(new InputStreamReader(pr.getInputStream()));
  43. while ((line = prReader.readLine()) != null) {
  44. if (line.contains(processName)) { value = true; break; }
  45. }
  46. } else {
  47. String winDir = System.getenv("windir") + "/System32/tasklist.exe";
  48. process = new ProcessBuilder(winDir);
  49. pr = process.start();
  50. String line;
  51. prReader = new BufferedReader(new InputStreamReader(pr.getInputStream()));
  52. while ((line = prReader.readLine()) != null) {
  53. if (line.contains(processName)) { value = true; break; }
  54. }
  55. }
  56. return value;
  57. }
  58. public String executeProcessReturnError(String processName, String arg) throws IOException {
  59. process = new ProcessBuilder(processName, arg);
  60. process.redirectError();
  61. pr = process.start();
  62. prReader = new BufferedReader(new InputStreamReader(pr.getErrorStream()));
  63. String line;
  64. String output = "";
  65. while ((line = prReader.readLine()) != null) {
  66. output += line + "\n";
  67. }
  68. return output;
  69. }
  70. }
yzuktlbb

yzuktlbb1#

是的,你可以用 SwingWorker 这样做的目的是,如果一个任务需要在一个单独的线程(后台线程)中运行很多时间,那么您就不会阻塞gui,jframe也不会冻结。这里有一个完整的例子,我真的很喜欢swing worker的例子。
基本上,作为一个示例,您创建了自己的类来扩展 SwingWorker 覆盖 doInBackground .
注意:您可以像普通类一样拥有字段。
例子:

  1. class Worker extends SwingWorker<Void, String> {
  2. private SomeClass businessDelegate;
  3. private JLabel label;
  4. @Override
  5. protected Void doInBackground() throws Exception {
  6. //here you make heavy task this is running in another thread not in EDT
  7. businessDelegate.callSomeService();
  8. setProgress(30); // this is if you want to use with a progressBar
  9. businessDelegate.saveToSomeDataBase();
  10. publish("Processes where saved");
  11. return null;
  12. }
  13. @Override
  14. protected void process(List<String> chunks){
  15. //this is executed in EDT you can update a label for example
  16. label.setText(chunks.toString());
  17. }
  18. //add setters for label and businessDelegate
  19. }

你也读过
process(..) publish(..) 以及 done() .
在你的客户代码里。

  1. SwingWorker<Void,String> myWorker = new Worker();
  2. myWorker.execute();
展开查看全部
tmb3ates

tmb3ates2#

您需要在单独的线程中运行代码。在程序中运行和协调多条代码路径的关键字是“并发”:
http://docs.oracle.com/javase/tutorial/essential/concurrency/index.html
多线程代码可能会变得非常棘手,并且很难调试,但是java提供了一些更高级别的抽象/概念,使得使用多线程代码时不太容易出错。
看看java.util.concurrent包中的这些概念。
由于多线程是使用awt/swing时必然遇到的问题,因此有一些实用程序类/方法是专门为图形应用程序中的多线程设计的。swingworker就是其中之一(另一个是swingutilities.invokelater())。熟悉它们是个好主意,它们可以让您的生活更轻松,特别是对于那些只需要足够长的时间就可以冻结gui的简单任务。

cigdeys3

cigdeys33#

如果你使用的是swing,swingworker就是一种方法。
既然你提到你不明白它是怎么工作的,我就给你一个简单的解释。
swing事件处理代码在事件调度线程中完成。因此,如果用户单击一个按钮(比如从服务器获取数据并在窗口中显示它们的update按钮),那么该按钮的actionlistener将在事件调度线程中调用。
如果您在同一个线程中获取数据,那么ui将冻结,因为它无法处理任何事件(您正在事件调度线程中运行代码)。
因此,您应该在单独的线程中获取数据。但是在获取数据之后,应该将其设置为事件调度线程中的视图。
秋千工人让你很容易。你把这项繁重的任务推到了最后 doInBackground 方法(在本例中是获取数据)并从该方法返回繁重任务的输出(在本例中是数据)。
done 方法调用 get 方法中返回的数据 doInBackground 方法。在那里,用新数据更新视图(例如,将数据添加到tablemodel)。
当你打电话的时候 exectue 在你的秋千工人现在,它将负责运行 doInBackground 在一个单独的线程(不是事件调度线程)中,它将运行 done 事件调度线程中的方法。
因此,通过使用swingworker,您不必担心在edt中处理ui事件的内部过程以及在另一个线程中耗时的任务。

相关问题