Kotlin / anko多个异步任务

时间:2016-06-01 14:00:56

标签: android asynchronous kotlin anko

我正在寻找一种简单的方法来并行启动多个任务并等待所有这些任务完成。

考虑这个c#示例:

private static void Main(string[] args)
{
    var urlList = new[] {"http://www.microsoft.com/", "http://www.google.com/", "http://www.apple.com/" };
    var result = GetHtml(urlList);
}

private static List<string> GetHtml(string[] urlList)
{
    var tasks = new List<Task>();
    var output = new List<string>();

    foreach (var url in urlList)
    {
        var task = new Task(() =>
        {
            var html = new WebClient().DownloadString(url);
            output.Add(html);
        });

        tasks.Add(task);

        //starts task in a separate thread (doesn't block anything)
        task.Start();
    }

    //waits for all tasks (running in parallel) to complete before exiting method
    Task.WaitAll(tasks.ToArray());

    return output;
}

GetHtml方法并行下载多个网页并返回一个html字符串列表。

如何使用kotlin / anko实现这一目标?

private fun GetHtml(urlList: Array<String>): ArrayList<String> {

    val tasks = ArrayList<Future<Unit>>()
    val output = ArrayList<String>()

    for (url in urlList) {
        val task = async() {
            //some java-code that downloads html from <url>, doesn't matter for now
            output.add("html for $url")
        }
        tasks.add(task)
    }

    //this is NOT parallel execution
    for (task in tasks) {
        task.get()           
    }

    //tasks.getall() ?? 

    return output
}

2 个答案:

答案 0 :(得分:2)

根据Michaelpdegand59的输入,这是一个有效的解决方案:

private fun GetHtml(urlList: Array<String>): ArrayList<String> {

    val pool = Executors.newFixedThreadPool(urlList.count())
    val countDownLatch = CountDownLatch(urlList.count())

    val output = ArrayList<String>()

    for (url in urlList) {  

        async(pool, {
            //some java-code that downloads html for <url>
            output.add("html for $url")
            countDownLatch.countDown()
        })      
    }

    countDownLatch.await()

    return output
}

答案 1 :(得分:1)

我建议在单独的线程中使用CountDownLatch以避免在所有并行下载期间阻塞主线程:

private fun downloadAllHtml(urlList: Array<String>) {
  val output = ArrayList<String>()
  val countDownLatch = CountDownLatch(urlList.length)

  async(Executors.newSingleThreadExecutor() {
    countDownLatch.await()
    uiThread {
      onAllHtmlDownloaded(output)
    }
  }

  urlList.forEach { url: String ->
    async() {
      // download stuff
      output.add("stuff downloaded")
      countDownLatch.countDown()
    }
  }
  // this method ends instantly, not blocking the main thread
}

private fun onAllHtmlDownloaded(output: ArrayList<String>) {
  // all your html, on the main thread
}

您可能需要添加一些try / catch。 IDE将帮助您;)