Java 让一个荡秋千的人睡觉
我有一个Swing GUI,它应该定期读取rss提要(提要由我编写的应用程序提供)。我已经在一个SwingWorker中实现了这一点,我想问一下这是否是一个合理的设计 以下是我为后台方法编写的代码:Java 让一个荡秋千的人睡觉,java,multithreading,swing,swingworker,rss-reader,Java,Multithreading,Swing,Swingworker,Rss Reader,我有一个Swing GUI,它应该定期读取rss提要(提要由我编写的应用程序提供)。我已经在一个SwingWorker中实现了这一点,我想问一下这是否是一个合理的设计 以下是我为后台方法编写的代码: @Override protected Void doInBackground() throws Exception { comboBoxModel.removeAllElements(); while(true) { Channel feedChannel =
@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);
}
}
@覆盖
受保护的Void doInBackground()引发异常{
comboBoxModel.removeAllElements();
while(true){
Channel feedChannel=webResource.path(role.role())
.accept(MyMediaType.APPLICATION\u RSS)
.get(Rss.class).getChannel();
List itemList=feedChannel.getEntryList();
用于(项目:项目列表){
字符串itemLink=item.getLink();
如果(!feedItemMap.containsKey(itemLink)){
comboBoxModel.addElement(新对(itemLink,true));
feedItemMap.put(itemLink,true);
}
}
睡眠(10000);
}
}
我让线程睡眠的想法是减少GET的数量。我的程序不需要每毫秒更新一次,所以为了减少服务器负载,我认为这是个好主意
读完这个问题()后,我现在很困惑这到底是不是一个好主意。我收集到的信息是,您通常不会让后台线程休眠,因为系统会处理它
然而,就我而言,这种方法似乎对我有益
是否有人可以详细说明此实现可能存在的问题
欢迎您的任何意见。这适用于特定主题以及总体设计。如果我做错了什么,我想知道。:)
问候语使用ScheduledExecutor服务:
ScheduledExecutorService ses = Executors.newSingleScheduledExecutorService();
ses.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
doInBackground();
}
}, 10, TimeUnit.SECONDS);
然后去掉线程。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);
}
}
}
protectedvoid doInBackground()引发异常{
comboBoxModel.removeAllElements();
Channel feedChannel=webResource.path(role.role())
.accept(MyMediaType.APPLICATION\u RSS)
.get(Rss.class).getChannel();
List itemList=feedChannel.getEntryList();
用于(项目:项目列表){
字符串itemLink=item.getLink();
如果(!feedItemMap.containsKey(itemLink)){
comboBoxModel.addElement(新对(itemLink,true));
feedItemMap.put(itemLink,true);
}
}
}
swing executor(在我的调试机器上)只为所有SwingWorker启动10个线程。这意味着,如果有10个任务处于休眠状态,则在其中一个任务返回之前,无法启动更多的任务。但是,您可以将SwingWorker提交给任何执行者进行处理,而不是依赖默认执行者
代码中还有另一个问题,即您从另一个线程访问gui对象,您应该发布这对对象,并使用process方法来处理它:
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);
}
}
if(!feedItemMap.containsKey(itemLink)){
发布(项目链接);
}
公共作废流程(列表字符串){
for(字符串str:strings){
comboBoxModel.addElement(新对(str,true));
feedItemMap.put(str,true);
}
}
回答错误-doInBackground()是brigde to Worker线程,然后默认情况下从未通知EDT,更多信息请参见Oracle教程Swing中的Concurrency-关于事件分派线程的部分(ratchet freak使用的提示读取方法)1。这个问题没有答案。没有发布的进程没有应答,OP的提示为空,3。所有Swingworker的线程数为10,不正确,但为12。(并发运行)可能会为SwingWorker生成无尽的bug(并非在所有JDK中都显示)@mKorbel调用SwingWorker上的execute
会在默认ExecutorService上提交它,如果它不存在,则会创建一个新的线程池执行器,其maximumPoolsize=10
。你仍然可以将它提交给你自己的执行者(可能有更多的线程)没问题。SwingWorker(尽管这个论坛很喜欢SwingWorker)不是个好主意,我建议使用标准(与SwingWorker相比简单、可管理、可设置)Runnable#Thread