2009-12-10 99 views
1

我正在创建一个包含一些动态生成图像的网页。如果需要的话等待结果

在我的页面请求处理中,我创建了所有图像并将它们存储在内存缓存中,直到它们随后被浏览器请求。

public class CachedImage 
{ 
    byte[] data; 
    Date created; 
} 

目前,我的图片缓存基本上是HashMap<Integer, CachedImage>

问题是,图像生成需要时间,并且我想在所有图像完成生成之前开始渲染页面。

所以我想生成一个线程池中的图像,并在请求时返回数据,如果它已准备就绪或等待数据准备好然后返回。

任何人都可以拿出这个机制的整洁模型?

图像很小,我很高兴现在在内存中缓存整个图像的方法。

回答

2

在生成页面时,为页面显示的每个图像选择一个新的唯一标识符。这可能简单得像是通过递增AtomicInteger获得的数字,或者它可能更像UUID那样复杂,以防止用户猜测其他用户的图像URL。将这些唯一标识符放入客户端用来检索图像的URL中。

一旦您选择了图像的标识符,构建一个Callable将生成并返回图像,并将其提交到ThreadPoolExecutor以异步运行。这给你一个Future可以用来检索结果。将未来保存在地图中,并将图像的标识符作为关键字。

后来,当客户端请求的图像,你可以把图像标识,并期待它在地图上找到相关的未来目标。在Future上调用get()将返回图像,并在必要时等待发生器完成。 (如果在地图中找不到所请求的标识符,返回404错误。)

为了避免填满服务器的旧影像的存储,你可能会想,几分钟后丢弃它们。为此,每次创建任务并将其Future放入可用图像的地图中时,都可以将任务放入DelayQueue中,该任务将在适当延迟后从地图中移除条目。使用守护进程线程从该队列中取得项目,并在循环中对其执行操作。

这也将会是一个好主意,从地图中删除它时,万一发电机仍在运行出于某种原因调用cancel(true)于未来。 (否则它会继续运行,即使图像将不再是可访问的反正。)

+0

几乎我现在得到的。 – pstanton 2009-12-10 05:51:00

0

你可以从当前请求删除整个逻辑与异步请求(AJAX),这甚至可以让你有一个“正在载入”图标,并控制超时和这样

+0

好主意,但对图像的渲染参数的复杂性使得很难去耦合的单个图像。我已经做出了这样一个呼吁,即一代人需要在一点上初始化,并且必须坚持下去。 – pstanton 2009-12-10 04:55:16

0

当渲染图像客户端(浏览器)请求一个网页,但实际上当时并没有获取图像。当它呈现页面并找到标签时,浏览器会将每个图像的不同请求发回服务器。这意味着您可以在图像存在之前发送HTML页面。

因此烧掉你的HTML响应,发送图像创建请求到你的图像服务。浏览器解析响应并从Web服务器请求图像。

您可以通过让另一个线程池通过接受单个线程中的请求来响应图像请求,并在图像准备就绪时做出响应,从而使它更上一层楼。如果您只是尽可能快地生成图像,并让网络服务器响应图像请求,则您的用户将获得404个尚未生成图像的响应。

+0

你错过了这一点,但谢谢。 – pstanton 2009-12-10 05:10:24

1

听起来像是你需要像futuretask东西

http://java.sun.com/j2se/1.5.0/docs/api/java/util/concurrent/Future.html

刚刚推出了一群人,你可以拉回来,结果当isDone是真实的,你甚至可以在等待他们完成封锁简单地调用get()。

+0

已经远远更加适应现在一个线程池 – pstanton 2009-12-10 05:38:25

+0

结合这一点,因为图像的一半是由时间上的浏览器的页面加载就绪,该解决方案比其他两个建议的方式更快。 – pstanton 2009-12-10 05:42:06

+0

我会双倍upvote如果我可以,但wyzard提供更多的信息。你让我在正确的道路上,谢谢。 – pstanton 2009-12-10 10:39:31