У меня есть GUI Swing, который должен периодически читать rss-канал (фид предоставляется приложением, которое я написал). Я реализовал это в SwingWorker и хочу спросить, является ли это звуковой дизайн.
Вот код, который я написал для фонового метода:
@Override
protected Void doInBackground() throws Exception {
comboBoxModel.removeAllElements();
while(true) {
Channel feedChannel = webResource.path(role.role())
.accept(MyMediaType.APPLICATION_RSS)
.get(Rss.class).getChannel();
List<Item> itemList = feedChannel.getEntryList();
for(Item item : itemList) {
String itemLink = item.getLink();
if(!feedItemMap.containsKey(itemLink)) {
comboBoxModel.addElement(new Pair<>(itemLink, true));
feedItemMap.put(itemLink, true);
}
}
Thread.sleep(10000);
}
}
Моя идея позволить потоку спать - уменьшить количество GET. Моя программа не должна обновляться каждые миллисекунды, поэтому для снижения нагрузки на сервер я думал, что это будет хорошей идеей.
Прочитав этот вопрос (java - thread.sleep() в SwingWorker), я теперь запутался, если это было хорошей идеей. Я собрал то, что вы обычно не пропускаете фоновый поток, потому что система позаботится об этом.
Однако в моем случае этот метод кажется мне полезным.
Может ли кто-нибудь уточнить возможные проблемы с этой реализацией?
Любой вход оценивается. Это касается конкретной темы, а также общего дизайна. Если я делаю что-то неправильно, я хочу это знать. :)
Приветствую
Используйте службу ScheduledExecutorService:
ScheduledExecutorService ses = Executors.newSingleScheduledExecutorService();
ses.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
doInBackground();
}
}, 10, TimeUnit.SECONDS);
И избавиться от Thread.sleep
и цикла while(true)
:
protected Void doInBackground() throws Exception {
comboBoxModel.removeAllElements();
Channel feedChannel = webResource.path(role.role())
.accept(MyMediaType.APPLICATION_RSS)
.get(Rss.class).getChannel();
List<Item> itemList = feedChannel.getEntryList();
for(Item item : itemList) {
String itemLink = item.getLink();
if(!feedItemMap.containsKey(itemLink)) {
comboBoxModel.addElement(new Pair<>(itemLink, true));
feedItemMap.put(itemLink, true);
}
}
}
Исполнитель swing (на моей машине отладки) запускает только 10 потоков для всех SwingWorkers. Это означает, что если 10 задач спят, больше никаких задач не может быть начато до тех пор, пока не вернется. однако вы можете отправить SwingWorker любому исполнителю для обработки вместо того, чтобы полагаться на исполнителя по умолчанию.
В вашем коде есть еще одна проблема, когда вы обращаетесь к объекту gui из другого потока, вместо этого вы должны publish
пару и использовать метод процесса для его обработки:
if(!feedItemMap.containsKey(itemLink)) {
publish(itemLink);
}
public void process(List<String> strings){
for(String str: strings){
comboBoxModel.addElement(new Pair<>(str, true));
feedItemMap.put(str, true);
}
}
execute
для свингворкера, отправляет его на ExecutorService по умолчанию, если он не существует, то он создает нового исполнителя ThreadPool с maximumPoolsize = 10
. Вы все еще можете отправить его своему собственному исполнителю (с потенциально большим количеством потоков) без проблем.