我正在尝试从服务器加载数据。然后通过JavaFX视图显示已加载的数据。我正在使用服务来执行网络操作,为此我正在使用Apache HttpClients。最初,我认为该错误与网络有关。我已经做了一些穴居人风格的调试,并且意识到该错误与服务相关。奇怪的是,该服务在第二次运行时会调用onSucceeded()方法(不同的实例,我不会重新启动该服务)。我无法弄清楚为什么该服务仅第二次调用onSucceeded()方法。
这是我为执行联网操作而实现的服务类。
public class HttpClientService extends Service<String> {
private static final String TAG = HttpClientService.class.getName();
private static final Logger logger = Logger.getLogger(TAG);
private ObjectProperty<URL> url = new SimpleObjectProperty<>();
private ObservableList<NameValuePair> parameters = FXCollections.observableArrayList();
public HttpClientService(String url, Map<String, String> map) throws MalformedURLException {
setUrl(new URL(url));
for (String name : map.keySet()) {
String value = map.get(name);
parameters.add(new BasicNameValuePair(name, value));
}
}
public HttpClientService(String url, NameValuePair ... parameters) throws MalformedURLException {
setUrl(new URL(url));
getParameters().addAll(parameters);
}
public HttpClientService(URL url, NameValuePair ... parameters) {
setUrl(url);
getParameters().addAll(parameters);
}
protected Task<String> createTask() {
return new HttpClientTask(getUrl(), getParameters());
}
public URL getUrl() {
return url.get();
}
public ObjectProperty<URL> urlProperty() {
return url;
}
public void setUrl(URL url) {
this.url.set(url);
}
public ObservableList<NameValuePair> getParameters() {
return parameters;
}
public void setParameters(ObservableList<NameValuePair> parameters) {
this.parameters = parameters;
}
@Override
protected void succeeded() {
System.out.println("## Successful...");
}
@Override
protected void failed() {
Throwable exception = getException();
System.out.println("Error: Failed to download guest profiles.");
exception.printStackTrace();
}
@Override
protected void cancelled() {
System.out.println("HttpClientService was stopped.");
}
@Override
protected void running() {
logger.log(Level.INFO, "Running service...");
}
}
这是调用服务并将数据注入视图的方法。
private void loadBlocks() {
try {
// TODO: Get the property identifier and set!
Integer propertyIdentifier = 1;
Map<String, String> parameters = new HashMap<>();
parameters.put("property", propertyIdentifier.toString());
HttpClientService service = new HttpClientService(UrlPath.ADMINISTRATION_PROPERTY_BLOCK_LIST_ALL, parameters);
service.setOnSucceeded(workerStateEvent -> {
logger.log(Level.INFO, "Successfully loaded blocks");
try {
String result = (String)workerStateEvent.getSource().getValue();
logger.log(Level.INFO, result);
List<Block> blocks = mapper.readValue(result, new TypeReference<ArrayList<Block>>(){});
ObservableList<Block> items = blocksTableView.getItems();
items.clear();
items.addAll(blocks);
NotificationHelper.postNotification(eventBus, "Successfully loaded blocks", 500);
}
catch (IOException exception) {
exception.printStackTrace();
}
});
service.stateProperty().addListener((observableValue, state, t1) -> System.out.println(t1));
service.start();
}
catch (MalformedURLException exception) {
exception.printStackTrace();
}
}
这是应用程序的日志。
SCHEDULED
RUNNING
Nov 10, 2018 2:28:26 PM com.onecube.pms.client.service.HttpClientService running
INFO: Running service...
Nov 10, 2018 2:28:26 PM com.onecube.pms.client.task.HttpClientTask call
INFO: [Content-Type: application/x-www-form-urlencoded,Content-Length: 10,Chunked: false]
14:28:26.778 [Thread-3] DEBUG org.apache.http.client.protocol.RequestAddCookies - CookieSpec selected: default
14:28:26.794 [Thread-3] DEBUG org.apache.http.client.protocol.RequestAuthCache - Auth cache not set in the context
14:28:26.796 [Thread-3] DEBUG org.apache.http.impl.conn.PoolingHttpClientConnectionManager - Connection request: [route: {}->http://localhost:8080][total kept alive: 0; route allocated: 0 of 100; total allocated: 0 of 200]
14:28:26.809 [Thread-3] DEBUG org.apache.http.impl.conn.PoolingHttpClientConnectionManager - Connection leased: [id: 0][route: {}->http://localhost:8080][total kept alive: 0; route allocated: 1 of 100; total allocated: 1 of 200]
14:28:26.810 [Thread-3] DEBUG org.apache.http.impl.execchain.MainClientExec - Opening connection {}->http://localhost:8080
14:28:26.829 [Thread-3] DEBUG org.apache.http.impl.conn.DefaultHttpClientConnectionOperator - Connecting to localhost/127.0.0.1:8080
14:28:26.830 [Thread-3] DEBUG org.apache.http.impl.conn.DefaultHttpClientConnectionOperator - Connection established 127.0.0.1:63671<->127.0.0.1:8080
14:28:26.831 [Thread-3] DEBUG org.apache.http.impl.execchain.MainClientExec - Executing request POST /administration/property/block/listAll HTTP/1.1
14:28:26.831 [Thread-3] DEBUG org.apache.http.impl.execchain.MainClientExec - Target auth state: UNCHALLENGED
14:28:26.834 [Thread-3] DEBUG org.apache.http.impl.execchain.MainClientExec - Proxy auth state: UNCHALLENGED
14:28:26.836 [Thread-3] DEBUG org.apache.http.headers - http-outgoing-0 >> POST /administration/property/block/listAll HTTP/1.1
14:28:26.836 [Thread-3] DEBUG org.apache.http.headers - http-outgoing-0 >> Content-Length: 10
14:28:26.836 [Thread-3] DEBUG org.apache.http.headers - http-outgoing-0 >> Content-Type: application/x-www-form-urlencoded
14:28:26.836 [Thread-3] DEBUG org.apache.http.headers - http-outgoing-0 >> Host: localhost:8080
14:28:26.836 [Thread-3] DEBUG org.apache.http.headers - http-outgoing-0 >> Connection: Keep-Alive
14:28:26.836 [Thread-3] DEBUG org.apache.http.headers - http-outgoing-0 >> User-Agent: Apache-HttpClient/4.5.6 (Java/11.0.1)
14:28:26.836 [Thread-3] DEBUG org.apache.http.headers - http-outgoing-0 >> Accept-Encoding: gzip,deflate
14:28:26.837 [Thread-3] DEBUG org.apache.http.wire - http-outgoing-0 >> "POST /administration/property/block/listAll HTTP/1.1[\r][\n]"
14:28:26.837 [Thread-3] DEBUG org.apache.http.wire - http-outgoing-0 >> "Content-Length: 10[\r][\n]"
14:28:26.837 [Thread-3] DEBUG org.apache.http.wire - http-outgoing-0 >> "Content-Type: application/x-www-form-urlencoded[\r][\n]"
14:28:26.837 [Thread-3] DEBUG org.apache.http.wire - http-outgoing-0 >> "Host: localhost:8080[\r][\n]"
14:28:26.837 [Thread-3] DEBUG org.apache.http.wire - http-outgoing-0 >> "Connection: Keep-Alive[\r][\n]"
14:28:26.837 [Thread-3] DEBUG org.apache.http.wire - http-outgoing-0 >> "User-Agent: Apache-HttpClient/4.5.6 (Java/11.0.1)[\r][\n]"
14:28:26.837 [Thread-3] DEBUG org.apache.http.wire - http-outgoing-0 >> "Accept-Encoding: gzip,deflate[\r][\n]"
14:28:26.837 [Thread-3] DEBUG org.apache.http.wire - http-outgoing-0 >> "[\r][\n]"
14:28:26.838 [Thread-3] DEBUG org.apache.http.wire - http-outgoing-0 >> "property=1"
14:28:26.845 [Thread-3] DEBUG org.apache.http.wire - http-outgoing-0 << "HTTP/1.1 200 [\r][\n]"
14:28:26.846 [Thread-3] DEBUG org.apache.http.wire - http-outgoing-0 << "Content-Type: application/json;charset=UTF-8[\r][\n]"
14:28:26.846 [Thread-3] DEBUG org.apache.http.wire - http-outgoing-0 << "Transfer-Encoding: chunked[\r][\n]"
14:28:26.846 [Thread-3] DEBUG org.apache.http.wire - http-outgoing-0 << "Date: Sat, 10 Nov 2018 08:58:26 GMT[\r][\n]"
14:28:26.846 [Thread-3] DEBUG org.apache.http.wire - http-outgoing-0 << "[\r][\n]"
14:28:26.846 [Thread-3] DEBUG org.apache.http.wire - http-outgoing-0 << "2[\r][\n]"
14:28:26.846 [Thread-3] DEBUG org.apache.http.wire - http-outgoing-0 << "[][\r][\n]"
14:28:26.846 [Thread-3] DEBUG org.apache.http.wire - http-outgoing-0 << "0[\r][\n]"
14:28:26.846 [Thread-3] DEBUG org.apache.http.wire - http-outgoing-0 << "[\r][\n]"
14:28:26.850 [Thread-3] DEBUG org.apache.http.headers - http-outgoing-0 << HTTP/1.1 200
14:28:26.850 [Thread-3] DEBUG org.apache.http.headers - http-outgoing-0 << Content-Type: application/json;charset=UTF-8
java.lang.Throwable
at com.onecube.pms.client.task.HttpClientTask.call(HttpClientTask.java:81)
at com.onecube.pms.client.task.HttpClientTask.call(HttpClientTask.java:32)
at javafx.concurrent.Task$TaskCallable.call(Task.java:1425)
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
at javafx.concurrent.Service.lambda$executeTask$6(Service.java:725)
at java.base/java.security.AccessController.doPrivileged(Native Method)
at javafx.concurrent.Service.lambda$executeTask$7(Service.java:724)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
at java.base/java.lang.Thread.run(Thread.java:834)
14:28:26.850 [Thread-3] DEBUG org.apache.http.headers - http-outgoing-0 << Transfer-Encoding: chunked
14:28:26.850 [Thread-3] DEBUG org.apache.http.headers - http-outgoing-0 << Date: Sat, 10 Nov 2018 08:58:26 GMT
14:28:26.856 [Thread-3] DEBUG org.apache.http.impl.execchain.MainClientExec - Connection can be kept alive indefinitely
14:28:26.860 [Thread-3] DEBUG org.apache.http.impl.conn.PoolingHttpClientConnectionManager - Connection [id: 0][route: {}->http://localhost:8080] can be kept alive indefinitely
14:28:26.861 [Thread-3] DEBUG org.apache.http.impl.conn.DefaultManagedHttpClientConnection - http-outgoing-0: set socket timeout to 0
14:28:26.861 [Thread-3] DEBUG org.apache.http.impl.conn.PoolingHttpClientConnectionManager - Connection released: [id: 0][route: {}->http://localhost:8080][total kept alive: 1; route allocated: 1 of 100; total allocated: 1 of 200]
SCHEDULED
RUNNING
Nov 10, 2018 2:28:43 PM com.onecube.pms.client.service.HttpClientService running
INFO: Running service...
Nov 10, 2018 2:28:43 PM com.onecube.pms.client.task.HttpClientTask call
INFO: [Content-Type: application/x-www-form-urlencoded,Content-Length: 10,Chunked: false]
14:28:43.429 [Thread-4] DEBUG org.apache.http.client.protocol.RequestAddCookies - CookieSpec selected: default
14:28:43.430 [Thread-4] DEBUG org.apache.http.client.protocol.RequestAuthCache - Auth cache not set in the context
14:28:43.431 [Thread-4] DEBUG org.apache.http.impl.conn.PoolingHttpClientConnectionManager - Connection request: [route: {}->http://localhost:8080][total kept alive: 0; route allocated: 0 of 100; total allocated: 0 of 200]
14:28:43.431 [Thread-4] DEBUG org.apache.http.impl.conn.PoolingHttpClientConnectionManager - Connection leased: [id: 1][route: {}->http://localhost:8080][total kept alive: 0; route allocated: 1 of 100; total allocated: 1 of 200]
14:28:43.431 [Thread-4] DEBUG org.apache.http.impl.execchain.MainClientExec - Opening connection {}->http://localhost:8080
14:28:43.431 [Thread-4] DEBUG org.apache.http.impl.conn.DefaultHttpClientConnectionOperator - Connecting to localhost/127.0.0.1:8080
14:28:43.432 [Thread-4] DEBUG org.apache.http.impl.conn.DefaultHttpClientConnectionOperator - Connection established 127.0.0.1:63675<->127.0.0.1:8080
14:28:43.432 [Thread-4] DEBUG org.apache.http.impl.execchain.MainClientExec - Executing request POST /administration/property/block/listAll HTTP/1.1
14:28:43.432 [Thread-4] DEBUG org.apache.http.impl.execchain.MainClientExec - Target auth state: UNCHALLENGED
14:28:43.433 [Thread-4] DEBUG org.apache.http.impl.execchain.MainClientExec - Proxy auth state: UNCHALLENGED
14:28:43.433 [Thread-4] DEBUG org.apache.http.headers - http-outgoing-1 >> POST /administration/property/block/listAll HTTP/1.1
14:28:43.434 [Thread-4] DEBUG org.apache.http.headers - http-outgoing-1 >> Content-Length: 10
14:28:43.434 [Thread-4] DEBUG org.apache.http.headers - http-outgoing-1 >> Content-Type: application/x-www-form-urlencoded
14:28:43.434 [Thread-4] DEBUG org.apache.http.headers - http-outgoing-1 >> Host: localhost:8080
14:28:43.434 [Thread-4] DEBUG org.apache.http.headers - http-outgoing-1 >> Connection: Keep-Alive
14:28:43.434 [Thread-4] DEBUG org.apache.http.headers - http-outgoing-1 >> User-Agent: Apache-HttpClient/4.5.6 (Java/11.0.1)
14:28:43.434 [Thread-4] DEBUG org.apache.http.headers - http-outgoing-1 >> Accept-Encoding: gzip,deflate
14:28:43.434 [Thread-4] DEBUG org.apache.http.wire - http-outgoing-1 >> "POST /administration/property/block/listAll HTTP/1.1[\r][\n]"
14:28:43.434 [Thread-4] DEBUG org.apache.http.wire - http-outgoing-1 >> "Content-Length: 10[\r][\n]"
14:28:43.434 [Thread-4] DEBUG org.apache.http.wire - http-outgoing-1 >> "Content-Type: application/x-www-form-urlencoded[\r][\n]"
14:28:43.434 [Thread-4] DEBUG org.apache.http.wire - http-outgoing-1 >> "Host: localhost:8080[\r][\n]"
14:28:43.434 [Thread-4] DEBUG org.apache.http.wire - http-outgoing-1 >> "Connection: Keep-Alive[\r][\n]"
14:28:43.434 [Thread-4] DEBUG org.apache.http.wire - http-outgoing-1 >> "User-Agent: Apache-HttpClient/4.5.6 (Java/11.0.1)[\r][\n]"
14:28:43.434 [Thread-4] DEBUG org.apache.http.wire - http-outgoing-1 >> "Accept-Encoding: gzip,deflate[\r][\n]"
14:28:43.435 [Thread-4] DEBUG org.apache.http.wire - http-outgoing-1 >> "[\r][\n]"
14:28:43.435 [Thread-4] DEBUG org.apache.http.wire - http-outgoing-1 >> "property=1"
java.lang.Throwable
at com.onecube.pms.client.task.HttpClientTask.call(HttpClientTask.java:81)
at com.onecube.pms.client.task.HttpClientTask.call(HttpClientTask.java:32)
at javafx.concurrent.Task$TaskCallable.call(Task.java:1425)
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
at javafx.concurrent.Service.lambda$executeTask$6(Service.java:725)
at java.base/java.security.AccessController.doPrivileged(Native Method)
at javafx.concurrent.Service.lambda$executeTask$7(Service.java:724)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
at java.base/java.lang.Thread.run(Thread.java:834)
Nov 10, 2018 2:28:43 PM com.onecube.pms.client.controller.administration.room.ManageBlocksController lambda$loadBlocks$2
INFO: Successfully loaded blocks
Nov 10, 2018 2:28:43 PM com.onecube.pms.client.controller.administration.room.ManageBlocksController lambda$loadBlocks$2
INFO: []
14:28:43.444 [Thread-4] DEBUG org.apache.http.wire - http-outgoing-1 << "HTTP/1.1 200 [\r][\n]"
14:28:43.449 [Thread-4] DEBUG org.apache.http.wire - http-outgoing-1 << "Content-Type: application/json;charset=UTF-8[\r][\n]"
14:28:43.449 [Thread-4] DEBUG org.apache.http.wire - http-outgoing-1 << "Transfer-Encoding: chunked[\r][\n]"
14:28:43.449 [Thread-4] DEBUG org.apache.http.wire - http-outgoing-1 << "Date: Sat, 10 Nov 2018 08:58:43 GMT[\r][\n]"
14:28:43.449 [Thread-4] DEBUG org.apache.http.wire - http-outgoing-1 << "[\r][\n]"
14:28:43.449 [Thread-4] DEBUG org.apache.http.wire - http-outgoing-1 << "2[\r][\n]"
14:28:43.449 [Thread-4] DEBUG org.apache.http.wire - http-outgoing-1 << "[][\r][\n]"
14:28:43.449 [Thread-4] DEBUG org.apache.http.wire - http-outgoing-1 << "0[\r][\n]"
14:28:43.449 [Thread-4] DEBUG org.apache.http.wire - http-outgoing-1 << "[\r][\n]"
14:28:43.450 [Thread-4] DEBUG org.apache.http.headers - http-outgoing-1 << HTTP/1.1 200
14:28:43.450 [Thread-4] DEBUG org.apache.http.headers - http-outgoing-1 << Content-Type: application/json;charset=UTF-8
14:28:43.450 [Thread-4] DEBUG org.apache.http.headers - http-outgoing-1 << Transfer-Encoding: chunked
14:28:43.451 [Thread-4] DEBUG org.apache.http.headers - http-outgoing-1 << Date: Sat, 10 Nov 2018 08:58:43 GMT
14:28:43.452 [Thread-4] DEBUG org.apache.http.impl.execchain.MainClientExec - Connection can be kept alive indefinitely
14:28:43.453 [Thread-4] DEBUG org.apache.http.impl.conn.PoolingHttpClientConnectionManager - Connection [id: 1][route: {}->http://localhost:8080] can be kept alive indefinitely
14:28:43.453 [Thread-4] DEBUG org.apache.http.impl.conn.DefaultManagedHttpClientConnection - http-outgoing-1: set socket timeout to 0
14:28:43.453 [Thread-4] DEBUG org.apache.http.impl.conn.PoolingHttpClientConnectionManager - Connection released: [id: 1][route: {}->http://localhost:8080][total kept alive: 1; route allocated: 1 of 100; total allocated: 1 of 200]
## Successful...
SUCCEEDED
答案 0 :(得分:1)
从向我们展示的内容来看,您的代码在任何地方都没有强烈引用HttpClientService
。这使我相信HttpClientService
在HttpClientTask
完成之前就是garbage collected。一些快速测试确认这是可能的。实际上documentation特别警告了这一点:
服务启动后,它将安排其任务并侦听任务状态的更改。任务不包含对启动它的服务的引用,这意味着正在运行的任务不会阻止服务被垃圾回收。
要解决此问题,您需要保留对HttpClientService
实例的强烈引用。这可以通过将其存储在loadBlocks()
所属的类中的某个位置来完成(假设也强烈引用了该类的实例)。然后,当服务终止时,您可以删除该引用(因为您当前不重用该服务)。另一个解决方案是直接使用HttpClientTask
,并且只有在准备就绪时才使用HttpClientService
来实现。
请注意,HttpClientTask
是 not 垃圾回收。这是因为通过执行Thread
可以很容易地到达它。因此,您的后台任务正常完成,但是不再有HttpClientService
通知您。
此外,第一次运行此代码与以后的任何时间都没有区别。它适用于第二次调用的事实真是太幸运了。每次调用此方法时,HttpClientService
都会进行垃圾回收;但是,不能保证垃圾收集周期会运行,这意味着您会不时地感到幸运。