Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 为什么在使用多线程appraoch后,我的GUI仍然冻结?_Java_Multithreading_Swing - Fatal编程技术网

Java 为什么在使用多线程appraoch后,我的GUI仍然冻结?

Java 为什么在使用多线程appraoch后,我的GUI仍然冻结?,java,multithreading,swing,Java,Multithreading,Swing,我已经使用基于MVC的java创建了一个基于GUI的应用程序。我的应用程序的主要任务是从互联网上获取一些数据并开始解析它 为了从internet获取数据,我使用以下类: public class WebReader implements Runnable { WebRecordResult WRResult = new WebRecordResult (); private void getData(args){ . . .

我已经使用基于MVC的java创建了一个基于GUI的应用程序。我的应用程序的主要任务是从互联网上获取一些数据并开始解析它

为了从internet获取数据,我使用以下类:

public class WebReader implements Runnable {
    WebRecordResult WRResult = new WebRecordResult ();
    private void    getData(args){
        .
        .
        .
        setResult(result);
    }

    public void run() {
        getData(args);
        WRResult.setResult(getResult());
    }

}


public class WebReaderResult {
    private AtomicReference<String> result = new AtomicReference<>("");

    public String getResult() {
        return result.get();
    }

    public void setResult(String s) {
        result.set(s);
    }
}
公共类WebReader实现可运行{
WebRecordResult WRResult=新的WebRecordResult();
私有void getData(args){
.
.
.
setResult(result);
}
公开募捐{
获取数据(args);
WRResult.setResult(getResult());
}
}
公共类WebReaderResult{
私有原子引用结果=新原子引用(“”);
公共字符串getResult(){
返回result.get();
}
公共void setResult(字符串s){
结果集(s);
}
}
在我的控制器中,我创建了如下内容:

WebReaderResult wrr = new WebReaderResult();

ExecutorService executor = Executors.newSingleThreadExecutor();
WebReader wr =new WebReader(args);
Future<?> f1 = executor.submit(wr);
executor.shutdown();
try {
    f1.get();
} catch (InterruptedException | ExecutionException e) {
    e.printStackTrace();
}
wrr.getResult(); 
WebReaderResult wrr=new WebReaderResult();
ExecutorService executor=Executors.newSingleThreadExecutor();
WebReader wr=新的WebReader(args);
未来f1=执行人提交(wr);
executor.shutdown();
试一试{
f1.get();
}捕获(中断异常|执行异常e){
e、 printStackTrace();
}
wrr.getResult();
使用此代码后,我的GUI仍然会冻结,直到数据可用为止。我不希望我的GUI被冻结。我该怎么办

注意:我的GUI是swing

f1.get();
阻塞,直到线程执行完毕。如果在UI线程中执行这一行,UI当然会冻结。但你对结果做了什么?如果没有更具体的代码,就很难给出问题的正确解决方案

**编辑**

控制器应该在自己的线程中执行和处理任务,并且应该与UI完全分离(对于适当的MVC模型)。由于您的代码中缺少信息(
args
,等等),示例如下:

结果 最后一个编辑没有第一个示例那么清晰,但是
SwingWorker
类确实提供了您所需要的内容。现在,您只需使用
WebReader
类(即通过调用
wr.run();
doInBackground
中,或通过其他方式)在
doInBackground
done
中委托处理。无论如何,我相信你现在有很多事情要做

f1.get();
阻塞,直到线程执行完毕。如果在UI线程中执行这一行,UI当然会冻结。但你对结果做了什么?如果没有更具体的代码,就很难给出问题的正确解决方案

**编辑**

控制器应该在自己的线程中执行和处理任务,并且应该与UI完全分离(对于适当的MVC模型)。由于您的代码中缺少信息(
args
,等等),示例如下:

结果 最后一个编辑没有第一个示例那么清晰,但是
SwingWorker
类确实提供了您所需要的内容。现在,您只需使用
WebReader
类(即通过调用
wr.run();
doInBackground
中,或通过其他方式)在
doInBackground
done
中委托处理。无论如何,我相信你现在有很多事情要做

我该怎么办

阅读文档。:)

严肃地说:

Future#get()
上的JavaDoc这样说(我强调):

根据需要等待计算完成,然后检索其结果

因此,您可以偶尔尝试调用
f1.isDone()
,直到它返回true,在这种情况下,您可以调用
get()

我该怎么办

阅读文档。:)

严肃地说:

Future#get()
上的JavaDoc这样说(我强调):

根据需要等待计算完成,然后检索其结果

因此,您可以偶尔尝试调用
f1.isDone()
,直到它返回true,在这种情况下,您可以调用
get()

代码f1.get()是一个阻塞调用

1) 您应该将您的任务分解为粒度单位,然后可能使用多个线程

2) 另外,使用回调机制而不是阻塞,您的任务应该接受一个完成侦听器并通知感兴趣的观察者任务完成,而不是进行阻塞调用。

代码f1.get()是一个阻塞调用

1) 您应该将您的任务分解为粒度单位,然后可能使用多个线程


2) 另外,使用回调机制而不是阻塞,您的任务应该接受一个完成侦听器,并将任务完成情况通知感兴趣的观察者,而不是直接进行阻塞调用。

来自官方javadocs(希望有一些有用的注释):


直接来自官方javadocs(希望有一些有用的评论):


Swing是单线程的。此线程的名称是事件调度线程(EDT)。当EDT中出现长时间运行的任务时,Swing应用程序将显示为冻结。为了避免这种情况,开发了一些实用程序,例如,
javax.swing.Timer
javax.swing.SwingUtilities
,以及
javax.swing.SwingWorker
。这些实用程序类确保修改Swing组件的任何操作都发生在EDT中,并且所有长时间运行的任务都发生在单独的线程(也称为后台线程)中


我建议您检查代码,并进一步研究哪些方法可以阻止线程(通常有文档记录)。之后,您可以通过在执行之前调用来检查这些方法是否出现在EDT中(这只是为了验证)。

Swing是单线程的。此线程的名称是事件调度线程(EDT)。秋千
public abstract class WebTask<V> {
   private WebReaderResult<V> res = new WebReaderResult<V>();

   public WebReaderResult<V> getWebReaderResult() { return res; }

   // handle task here
   public abstract void handle();
}
public interface WebControllerCallback<V> {
   public void done(V result);
}

public class WebController {
   static private WebController instance;
   static public WebController getInstance() {
      if (null == instance) instance = new WebController();
      return instance;
   }

   private ExecutorService executor = Executors.newSingleThreadExecutor();

   public void handleTask(WebTask<?> t, WebControllerCallback<?> cb) {
      executor.submit(new Runnable() {
         public void run() {
            t.handle();
            cb.done(t.getWebReaderResult());
         }
      });
   }

   // other methods here
}
WebTask<String> task = new WebTask<String>() {
   public void handle() {
      WebReaderResult<String> result = getWebReaderResult();

      // TODO : handle task and set result here result.getResult();
   }
};
WebControllerCallback<String> callback = new WebControllerCallback<String>() {
   public void done(String result) {
      // TODO : update UI here from result value
   }
};

WebController.getInstance().handleTask(task, callback);
new SwingWorker<String, Object>() {
   @Override
   protected String doInBackground() throws Exception {
      // TODO : process result

      return "some result";
   }

   protected void done() {
      // TODO : refresh UI with the value of this.get(); which return a String
   }
}.execute();
final JLabel label;
   class MeaningOfLifeFinder extends SwingWorker<String, Object> {
       @Override
       public String doInBackground() {
           // In here put the time consuming task
           return findTheMeaningOfLife();
       }

       @Override
       protected void done() {
           // In here you'd be in UI thread, so you can actually render some text in a JLabel
           try { 
               label.setText(get());
           } catch (Exception ignore) {
           }
       }
   }
   (new MeaningOfLifeFinder()).execute();