【发布时间】:2014-02-18 10:31:07
【问题描述】:
我有一组关键字(超过 600 个),我想使用流 api 来跟踪它们的推文。 Twitter api 将允许您跟踪的关键字数量限制为 200 个。因此,我决定使用多个线程来执行此操作,为此使用多个 OAuth 令牌。我就是这样做的:
String[] dbKeywords = KeywordImpl.listKeywords();
List<String[]> keywords = ditributeKeywords(dbKeywords);
for (String[] subList : keywords) {
StreamCrawler streamCrawler = new StreamCrawler();
streamCrawler.setKeywords(subList);
Thread crawlerThread = new Thread(streamCrawler);
crawlerThread.start();
}
这就是单词在线程中的分布方式。每个线程接收不超过 200 个单词。 这是 StreamCrawler 的实现:
public class StreamCrawler extends Crawler implements Runnable {
...
private String[] keywords;
public void setKeywords(String[] keywords) {
this.keywords = keywords;
}
@Override
public void run() {
TwitterStream twitterStream = getTwitterInstance();
StatusListener listener = new StatusListener() {
ArrayDeque<Tweet> tweetbuffer = new ArrayDeque<Tweet>();
ArrayDeque<TwitterUser> userbuffer = new ArrayDeque<TwitterUser>();
@Override
public void onException(Exception arg0) {
System.out.println(arg0);
}
@Override
public void onDeletionNotice(StatusDeletionNotice arg0) {
System.out.println(arg0);
}
@Override
public void onScrubGeo(long arg0, long arg1) {
System.out.println(arg1);
}
@Override
public void onStatus(Status status) {
...Doing something with message
}
@Override
public void onTrackLimitationNotice(int arg0) {
System.out.println(arg0);
try {
Thread.sleep(5 * 60 * 1000);
System.out.println("Will sleep for 5 minutes!");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
@Override
public void onStallWarning(StallWarning arg0) {
System.out.println(arg0);
}
};
FilterQuery fq = new FilterQuery();
String keywords[] = getKeywords();
System.out.println(keywords.length);
System.out.println("Listening for " + Arrays.toString(keywords));
fq.track(keywords);
twitterStream.addListener(listener);
twitterStream.filter(fq);
}
private long getCurrentThreadId() {
return Thread.currentThread().getId();
}
private TwitterStream getTwitterInstance() {
TwitterConfiguration configuration = null;
TwitterStream twitterStream = null;
while (configuration == null) {
configuration = TokenFactory.getAvailableToken();
if (configuration != null) {
System.out
.println("Token was obtained " + getCurrentThreadId());
System.out.println(configuration.getTwitterAccount());
setToken(configuration);
ConfigurationBuilder cb = new ConfigurationBuilder();
cb.setDebugEnabled(true);
cb.setOAuthConsumerKey(configuration.getConsumerKey());
cb.setOAuthConsumerSecret(configuration.getConsumerSecret());
cb.setOAuthAccessToken(configuration.getAccessToken());
cb.setOAuthAccessTokenSecret(configuration.getAccessSecret());
twitterStream = new TwitterStreamFactory(cb.build())
.getInstance();
} else {
// If there is no available configuration, wait for 2 minutes
// and try again
try {
System.out
.println("There were no available tokens, sleeping for 2 minutes.");
Thread.sleep(2 * 60 * 1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
return twitterStream;
}
}
所以我的问题是,当我启动例如 2 个线程时,我收到通知,它们都在打开流并获取它。但实际上只有第一个真正得到流并分别调用 OnStatus 方法。在第二个线程中使用的数组不为空; Twitter 配置也是有效且唯一的。所以我不明白这种行为可能是什么原因。为什么唯一的第一个线程返回推文?
【问题讨论】:
-
这很奇怪,因为一切似乎都是独一无二的。为什么不运行多个应用程序而不是在同一个应用程序中运行带有线程的流?
-
我没有想到这种方法,因为关键字的数量会增加,所以我必须运行5个以上的实例。此外,我会说这是不明智的,因为我看不出用不同的线程来做这件事有什么障碍。
-
我同意它应该以某种方式工作。如果您的密钥集很小,我只是提供了一个想法。 :D
标签: java multithreading twitter twitter4j