Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/317.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 使用twitter4j使用多线程从twitter获取数据_Java_Multithreading_Twitter_Twitter4j - Fatal编程技术网

Java 使用twitter4j使用多线程从twitter获取数据

Java 使用twitter4j使用多线程从twitter获取数据,java,multithreading,twitter,twitter4j,Java,Multithreading,Twitter,Twitter4j,我有一组关键字(超过600个),我想使用流式api来跟踪推文。Twitter api将允许跟踪的关键字数量限制为200个。因此,我决定使用几个OAuth标记,让几个线程来完成这项工作。我就是这样做的: String[] dbKeywords = KeywordImpl.listKeywords(); List<String[]> keywords = ditributeKeywords(dbKeywords); for (String[] subList : keyw

我有一组关键字(超过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();
    }
String[]dbKeywords=KeywordImpl.listKeywords();
列表关键字=双关键字(dbKeywords);
for(字符串[]子列表:关键字){
StreamCrawler StreamCrawler=新的StreamCrawler();
streamCrawler.setKeywords(子列表);
线程爬虫读取=新线程(streamCrawler);
crawlethread.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;
    }
}
公共类StreamCrawler扩展了Crawler实现Runnable{
...
私有字符串[]关键字;
public void setKeywords(字符串[]关键字){
这个.关键词=关键词;
}
@凌驾
公开募捐{
TwitterStream TwitterStream=getTwitterInstance();
StatusListener=新建StatusListener(){
ArrayDeque tweetbuffer=新的ArrayDeque();
ArrayDeque userbuffer=新的ArrayDeque();
@凌驾
public void onException(异常arg0){
系统输出打印项次(arg0);
}
@凌驾
公共作废onDeletionNotice(StatusDeletionNotice arg0){
系统输出打印项次(arg0);
}
@凌驾
CRUBGEO上的公共无效(长arg0,长arg1){
系统输出打印项次(arg1);
}
@凌驾
公共无效状态(状态){
…用信息做点什么
}
@凌驾
公开无效onTrackLimitationNotice(int arg0){
系统输出打印项次(arg0);
试一试{
线程睡眠(5*60*1000);
System.out.println(“将睡眠5分钟!”);
}捕捉(中断异常e){
e、 printStackTrace();
}
}
@凌驾
安装警告上的公共无效(安装警告arg0){
系统输出打印项次(arg0);
}
};
FilterQuery fq=新建FilterQuery();
字符串关键字[]=getKeywords();
System.out.println(关键字.长度);
System.out.println(“侦听”+数组.toString(关键字));
关键词;
twitterStream.addListener(listener);
twitterStream.filter(fq);
}
私有长getCurrentThreadId(){
返回Thread.currentThread().getId();
}
私有TwitterStream getTwitterInstance()的{
TwitterConfiguration=null;
TwitterStream TwitterStream=null;
while(配置==null){
configuration=TokenFactory.getAvailableToken();
if(配置!=null){
系统输出
.println(“已获取令牌”+getCurrentThreadId());
System.out.println(configuration.getTwitterAccount());
setToken(配置);
ConfigurationBuilder cb=新的ConfigurationBuilder();
cb.setDebugEnabled(true);
cb.setOAuthConsumerKey(configuration.getConsumerKey());
cb.setOAuthConsumerCret(configuration.getConsumerCret());
setOAuthAccessToken(configuration.getAccessToken());
cb.setOAuthAccessTokenSecret(configuration.getAccessSecret());
twitterStream=新TwitterStreamFactory(cb.build())
.getInstance();
}否则{
//如果没有可用的配置,请等待2分钟
//然后再试一次
试一试{
系统输出
.println(“没有可用的代币,睡了2分钟。”);
线程睡眠(2*60*1000);
}捕捉(中断异常e){
//TODO自动生成的捕捉块
e、 printStackTrace();
}
}
}
返回推特流;
}
}

所以我的问题是,当我启动例如2个线程时,我收到通知,它们都在打开流并获取它。但实际上只有第一个是真正获取流并分别调用OnStatus方法。第二个线程中使用的数组不是空的;Twitterconfiguration也是有效且唯一的。所以我不明白这种行为的原因是什么。为什么只有第一个线程返回tweets?

据我所知,您正试图从同一IP同时连接到公共流媒体端点(又称general streams或stream.twitter.com)。
更具体地说,我认为您需要从同一IP连接到stream.twitter.com/1.1/statuses/filter.json的两个活动连接

尽管Twitter流媒体api文档没有明确说明只有一个到公共端点的固定连接,但Twitter员工在dev站点上澄清了这一点

对于一般流,您应该只从同一IP建立一个连接

这意味着,使用两个不同的Twitter应用程序/帐户连接到公共流并不重要;只要您从同一IP地址连接,您就只能有一个到公共流的固定连接。你说你把两条流都连接起来了,对此行为的答案由一名Twitter员工给出:

你可能会发现,有时stream.twitter.com可以让你在这里或那里获得更多的开放连接,但这种行为不应该被指望

例如,如果您尝试在第二个线程中连接到用户流(twitter4j TwitterStream user()方法),那么您将真正开始获得过滤器和用户流

关于200个跟踪关键字的限制,twitter4j.org javadoc可能有点过时了。以下是twitter api文档所说的

默认的acc