我编写了以下Java代码:
twitterStream.addListener(new StreamListener());
FilterQuery filterQuery = new FilterQuery();
filterQuery.follow(filteringUsers);
filterQuery.track(filteringWords);
twitterStream.filter(filterQuery);
在Twitter中跟踪某些用户和关键字(通过Streaming API)。在这里,StreamListener
是我个人对听众的实现。
我正在跟踪很多关键字,主题标签和用户,因此我在内存中累积了很多等待处理的推文。实际上,我只是通过监听器(在onStatus()
方法中)并将它们刷新到数据库中。
但是,他们必须在内存中等待的事实显然会在几个小时内使内存饱和。在20分钟的运行中,我在内存中积累了177000个LinkedBlockingQueue$Node
个对象和1.272MB的char[]
(通过剖析看到)。
我想让管道继续运行,显然这在当前状态下是不可能的。
因此,我想知道是否有一种方法可以在多线程中添加多个侦听器,这样它们就可以同时清空推文队列并加快处理速度。
提前致谢。
答案 0 :(得分:1)
虽然通过Twitter4J无法实现直接多线程解决方案,但可以决定通过侦听器类来模拟多线程队列处理。
假设StreamListener
是您对StatusListener
Twitter4J听众的专长。
我们将StreamListener
内的队列复制为私有属性:
private LinkedBlockingQueue<String> tweets;
队列在构造函数中初始化:
tweets = new LinkedBlockingQueue<String>();
此外,在构造函数中,我们构建了一个线程池,用于从队列中读取推文(批量)并将它们存储在数据库中:
final ExecutorService executor = Executors.newFixedThreadPool(NUM_THREADS);
Runnable tweetAnalyzer = defineMonitoringRunnable(tweetRepository);
for (int i = 0; i < NUM_THREADS; i++) {
executor.execute(tweetAnalyzer);
try {
Thread.sleep(THREADS_DELAY);
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
可以按如下方式构建Runnable
对象:
private Runnable defineMonitoringRunnable(final TweetRepository tweetRepository) {
return new Runnable() {
@Override
public void run() {
List<String> tempTweets = new ArrayList<String>();
while (true) {
if (tweets.size() > 0) {
tempTweets.clear();
tweets.drainTo(tempTweets);
tweetRepository.insert(tempTweets);
}
try {
Thread.sleep(TWEETS_SAVING_TIME);
}
catch (InterruptedException ex) {
ex.printStackTrace();
}
}
}
};
}
(TWEETS_SAVING_TIME
是一个推文和另一个推文之间每个Thread
对象的等待时间。
最后,onStatus()
方法将推文一旦到达侦听器就将其存储在队列中:
@Override
public void onStatus(Status status) {
tweets.add(TwitterObjectFactory.getRawJSON(status));
}