使用Twitter4j提供的代码示例,我想在收集到1,000个状态列表后停止流,并返回此列表。我怎么能这样做?
public class Stream {
public List<Status> execute throws TwitterException {
List<Status> statuses = new ArrayList();
ConfigurationBuilder cb = new ConfigurationBuilder();
cb.setDebugEnabled(true);
cb.setOAuthConsumerKey("bbb");
cb.setOAuthConsumerSecret("bbb");
cb.setOAuthAccessToken("bbb");
cb.setOAuthAccessTokenSecret("bbb");
TwitterStream twitterStream = new TwitterStreamFactory(cb.build()).getInstance();
StatusListener listener = new StatusListener() {
public void onStatus(Status status) {
statuses.add(status);
if (statuses.size>1000){
//return statuses. Obviously that's not the correct place for a return statement...
}
}
public void onDeletionNotice(StatusDeletionNotice statusDeletionNotice) {
System.out.println("Got a status deletion notice id:" + statusDeletionNotice.getStatusId());
}
public void onTrackLimitationNotice(int numberOfLimitedStatuses) {
System.out.println("Got track limitation notice:" + numberOfLimitedStatuses);
}
public void onScrubGeo(long userId, long upToStatusId) {
System.out.println("Got scrub_geo event userId:" + userId + " upToStatusId:" + upToStatusId);
}
public void onException(Exception ex) {
ex.printStackTrace();
}
};
FilterQuery fq = new FilterQuery();
String keywords[] = {"Keyword 1", "Keyword 2"};
fq.track(keywords);
twitterStream.addListener(listener);
twitterStream.filter(fq);
}
答案 0 :(得分:6)
考虑使用BlockingQueue
作为中介,使用侦听器向其添加Status
个对象。
流启动后,您可以开始从队列中取Status
个es,直到您拥有所需的1000个。
作为起点,它看起来如下:
public class Stream {
private static final int TOTAL_TWEETS = 1000;
public List<Status> execute() throws TwitterException {
// skipped for brevity...
// TODO: You may have to tweak the capacity of the queue, depends on the filter query
final BlockingQueue<Status> statuses = new LinkedBlockingQueue<Status>(10000);
final StatusListener listener = new StatusListener() {
public void onStatus(Status status) {
statuses.offer(status); // Add received status to the queue
}
// etc...
};
final FilterQuery fq = new FilterQuery();
final String keywords[] = {"Keyword 1", "Keyword 2"};
fq.track(keywords);
twitterStream.addListener(listener);
twitterStream.filter(fq);
// Collect the 1000 statues
final List<Status> collected = new ArrayList<Status>(TOTAL_TWEETS);
while (collected.size() < TOTAL_TWEETS) {
// TODO: Handle InterruptedException
final Status status = statuses.poll(10, TimeUnit.SECONDS);
if (status == null) {
// TODO: Consider hitting this too often could indicate no further Tweets
continue;
}
collected.add(status);
}
twitterStream.shutdown();
return collected;
}
}
答案 1 :(得分:4)
强制异步代码进入同步模式并不是一个好主意。请参阅https://stackoverflow.com/a/5934656/276263 看看你是否可以修改你的逻辑。
但是,以下代码可根据您的要求运行。
public class Stream {
public static void main(String[] args) throws TwitterException {
Stream stream = new Stream();
stream.execute();
}
private final Object lock = new Object();
public List<Status> execute() throws TwitterException {
final List<Status> statuses = new ArrayList();
ConfigurationBuilder cb = new ConfigurationBuilder();
cb.setDebugEnabled(true);
cb.setOAuthConsumerKey("bbb");
cb.setOAuthConsumerSecret("bbb");
cb.setOAuthAccessToken("bbb");
cb.setOAuthAccessTokenSecret("bbb");
TwitterStream twitterStream = new TwitterStreamFactory(cb.build())
.getInstance();
StatusListener listener = new StatusListener() {
public void onStatus(Status status) {
statuses.add(status);
System.out.println(statuses.size() + ":" + status.getText());
if (statuses.size() > 100) {
synchronized (lock) {
lock.notify();
}
System.out.println("unlocked");
}
}
public void onDeletionNotice(
StatusDeletionNotice statusDeletionNotice) {
System.out.println("Got a status deletion notice id:"
+ statusDeletionNotice.getStatusId());
}
public void onTrackLimitationNotice(int numberOfLimitedStatuses) {
System.out.println("Got track limitation notice:"
+ numberOfLimitedStatuses);
}
public void onScrubGeo(long userId, long upToStatusId) {
System.out.println("Got scrub_geo event userId:" + userId
+ " upToStatusId:" + upToStatusId);
}
public void onException(Exception ex) {
ex.printStackTrace();
}
@Override
public void onStallWarning(StallWarning sw) {
System.out.println(sw.getMessage());
}
};
FilterQuery fq = new FilterQuery();
String keywords[] = { "federer", "nadal", "#Salute" };
fq.track(keywords);
twitterStream.addListener(listener);
twitterStream.filter(fq);
try {
synchronized (lock) {
lock.wait();
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("returning statuses");
twitterStream.shutdown();
return statuses;
}
}
答案 2 :(得分:0)
有两种方法:
如果您只需要完成使用流的线程(这是调用您的侦听器的线程),您可以使用twitterStream.cleanUp();
。这将优雅地停止线程。您可能希望在状态监听器中使用boolean stopped
变量,以便忽略此事件后您将收到的任何呼叫。
您还可以通过调用twitterStream.shutdown();
来关闭流消耗线程及其调度程序线程(即deamon线程)。但是,这是一种结束与twitter API通信的更残酷的方法。虽然如果你从监听器内部调用它,它可以工作,我更喜欢@krishnakumarp