1

我正在开发一个简单的 Spring MVC 应用程序来从流 API 下载推文并在网页中显示它们。该应用程序的用户可以提交Task他们想要下载的推文的关键字。此任务是共享的,因此每个人都可以开始、停止、修改、更改或取消任务。

TwitterFetcher是负责下载推文的类。此类接收一个任务并将所有下载的推文保存在数据库中。

@Service
public class TwitterFetcher {

    @Autowired
    private OAuthService oAuthService;

    @Autowired
    private TweetService tweetService;

    private Task task;
    private TwitterStream twitterStream;

    public void start(Task task) {
        /* Stop previous stream */
        stop();

        /* Get OAuth credentials */
        OAuth oAuth = oAuthService.findOneEnabled();

        if (oAuth == null) {

        } else {
            this.task = task;

            Configuration oAuthConfiguration = getOAuthConfiguration(oAuth);
            twitterStream = new TwitterStreamFactory(oAuthConfiguration).getInstance();
            twitterStream.addListener(new TwitterListener());

            String keywords = task.getBaseKeywords() + ", " + task.getExpandedKeywords();
            FilterQuery filterQuery = new FilterQuery();
            filterQuery.track(keywords.split(", "));
            twitterStream.filter(filterQuery);
        }
    }

    public void stop() {
        if (twitterStream != null) {
            twitterStream.shutdown();
        }
    }

    private Configuration getOAuthConfiguration(OAuth oAuth) {
        ConfigurationBuilder cb = new ConfigurationBuilder();
        cb.setDebugEnabled(false);
        cb.setJSONStoreEnabled(true);
        cb.setOAuthAccessToken(oAuth.getAccessToken());
        cb.setOAuthAccessTokenSecret(oAuth.getAccessTokenSecret());
        cb.setOAuthConsumerKey(oAuth.getConsumerKey());
        cb.setOAuthConsumerSecret(oAuth.getConsumerSecret());

        return cb.build();
    }

    private class TwitterListener implements StatusListener {

        @Override
        public void onStatus(Status status) {
            /* Persist new tweet */
            Tweet tweet = new Tweet();
            tweet.setJson(DataObjectFactory.getRawJSON(status));
            tweetService.save(tweet);
        }

        [Omitted code]
    }
}

基本功能将是下一个:

  1. 用户从网站启动 fetcher。
  2. 提取器收到一条新推文并将其保存在数据库中
  3. 提取器不断接收推文,直到用户停止它。

该应用程序有一个仪表板来控制 fetcher 和任务,并且用户必须能够在 fetcher 下载时与之交互。

我的问题是,提取器会阻止应用程序还是会在不同的线程中执行?在最坏的情况下,我必须改变什么来解决这个问题?我离一个可用的应用程序还很远,所以我无法测试它。即便如此,如果可能的话,我想立即修复它。

4

2 回答 2

1

您可以使用 ExecutorService 在单独的线程中运行 fetcher。我建议使用 ThreadPool 以便在运行 fetcher 的用户过多时不会降低性能:

ExecutorService executor = Executors.newFixedThreadPool(maxThreads)

当通过执行器提交任务时,它将返回一个Future对象,您可以从中检查作业是否完成

Future f = executor.submit(myTask);
boolean isDone = f.isDone();

如果您不熟悉,请阅读有关 Java 并发的更多信息:http: //docs.oracle.com/javase/tutorial/essential/concurrency/index.html

于 2013-06-05T23:03:24.473 回答
1

使用@Async注释您的 start() 方法。

@Async
public void start(Task task)

这将使启动方法异步并且不会阻塞应用程序。

您可以在此处查看一个简单的示例。

于 2013-06-05T23:03:34.640 回答