2016-06-01 2 views
1

Я ищу простой способ одновременного запуска нескольких задач и дождаться завершения их всех.Kotlin/anko multiple async tasks

Рассмотрим 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 
} 
+1

Возможно, есть лучший способ, но вы можете [указать 'ExecutorService' для' async'] (https://github.com/Kotlin/anko/blob/master/doc/ADVANCED .md # asynchronous-tasks), а 'ExecutorService' имеет метод' 'awaitTermination' '(https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ExecutorService.html#awaitTermination (длинный,% 20java.util.concurrent.TimeUnit)). – Michael

+1

С Kotlin 1.1.1 вы можете «ждать» одно или несколько заданий, см. Http://stackoverflow.com/a/43151714/882912 – KTCO

ответ

1

На основе информации из Michael и pdegand59, вот рабочий раствор:

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 
} 
0

Я хотел бы предложить использовать 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 
} 

Возможно, вам придется добавить попытку/уловку. IDE поможет вам;)

+0

CountDownLatch отлично смотрится, но предоставленный вами код не работает, к сожалению. onAllHtmlЗагруженный метод никогда не достигается, потому что countDownLatch.await() заставляет процесс ждать бесконечно. То, что я сделал, это создать отдельный ThreadPool и использовать countDownLatch.await(), это сработало нормально. – Fire095

+0

Я обновил код, переместив асинхронный вызов с ожиданием перед циклом и выполнив этот асинхронный вызов другого Исполнителя. – pdegand59

+0

Спасибо за ваш вклад! Проблема здесь не в CountDownLatch, а в блоках async(), которые загружают html. Блокирование основного потока не вызывает беспокойства в этом сценарии, поэтому дайте ему как можно проще :) Я обновил свой ответ и дал вам кредит – Fire095

Смежные вопросы