Java 从URL存储原始HTML内容,然后从内存获取InputStream(不使用连接)
我有一个涉及多线程的棘手问题。我所做的是使用线程池(Java 从URL存储原始HTML内容,然后从内存获取InputStream(不使用连接),java,multithreading,http,producer-consumer,Java,Multithreading,Http,Producer Consumer,我有一个涉及多线程的棘手问题。我所做的是使用线程池(ExecutorService),该线程池负责打开连接并将它们放入LinkedBlockingQueue 到目前为止,我使用了: //run method in "getter threads" public void run() { try { URL url = new URL(url_s); //url_s is given as a constructor argument //if I am correc
ExecutorService
),该线程池负责打开连接并将它们放入LinkedBlockingQueue
到目前为止,我使用了:
//run method in "getter threads"
public void run() {
try {
URL url = new URL(url_s); //url_s is given as a constructor argument
//if I am correct then url.openStream will wait until we have the content
InputStream stream = url.openStream();
Request req = new Request(); //a class with two variables:
req.html_stream = new InputSource(stream);
req.source = stream;
//this is a class variable (LinkedBlockingQueue<Request>)
blocking_queue.put(req);
} catch (Exception ex) {
logger.info("Getter thread died from an exeption",ex);
return;
}
}
其中eat_数据调用接受InputSource的外部库。该库使用一个单例实例进行处理,因此我不能将此步骤放在“getter”线程中
当我为少量数据测试这段代码时,它工作得很好,但当我为它提供数千个URL时,我开始遇到实际问题。要找出到底是什么问题并不容易,但我怀疑连接在使用者线程到达它们之前就超时了,有时甚至会导致死锁
我这样实现它是因为从url.openStream()到InputSource非常容易,但我意识到我必须将数据存储在本地才能工作
如何从url.openStream()获取某个对象,我可以将其存储在
LinkedBlockingQueue
(内存中的所有数据)中,当我的消费者线程有时间处理它时,我可以将其转换为输入或产生?您可以将url的内容复制到ByteArrayOutputStream
并关闭url流。然后将ByteArrayInputStream
存储在队列中
伪代码:
InputStream in = null;
try {
in = url.openStream();
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
IOUtils.copy(in, buffer);
ByteArrayInputStream bin = new ByteArrayInputStream(buffer.toByteArray());
queue.put(bin);
}
参考资料:
就我个人而言,我不会打开连接,直到你打开它们。我将URL:传递给
请求
对象,并让它在需要时打开连接。这还意味着您可以控制连接的关闭(您打开了它,您负责关闭它)。IMHO@MadProgrammer但是,这样是否就不需要等待连接的回复了?这就是我使用多线程的原因。使用“getter”线程是为了使处理器线程不需要等待IO(例如http响应)。不,这样的线程是为了减少活动连接(和资源)的数量,否则会消耗这些连接。仅在需要时打开连接,完成后关闭连接。在Windows上,您很快就会遇到问题,因为它对您可以打开的活动连接的数量有一个非常严格的上限,并且正如您所指出的,您无论如何都会遇到超时。我个人会使用请求
打开、阅读、存储和关闭URL中的内容。然后我会把它放在一个队列中,等待处理器线程出现,并在它可以自由处理时进行处理。。。
InputStream in = null;
try {
in = url.openStream();
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
IOUtils.copy(in, buffer);
ByteArrayInputStream bin = new ByteArrayInputStream(buffer.toByteArray());
queue.put(bin);
}