1

我有一个imageurl数组,通过DownloadFromUrl函数下载,从myfunction调用,我使用线程,我不知道有多少图像url,对于创建的每个图像下载单独线程,我想在所有这些线程之后启动一个活动结尾。

我怎么能得到所有这些线程,线程睡眠时间更长不能工作它不是一个好的过程。我也不能通过静态变量计数来计算线程结束,因为有时图像无法下载或 url 损坏,或者连接没有超时,

我现在有点迷茫,要弄清楚这些所有线程都结束了的程序是什么?

public void DownloadFromUrl(String DownloadUrl, String fileName) {

               try {
                       File root = android.os.Environment.getExternalStorageDirectory();               

                       File dir = new File (root.getAbsolutePath() + "/"+Imageurl.facebookpage);
                   if(dir.exists()==false) {
                        dir.mkdirs();
                   }

                   URL url = new URL(DownloadUrl); //you can write here any link
                   File file = new File(dir, fileName);



                   /* Open a connection to that URL. */
                   URLConnection ucon = url.openConnection();

                   /*
                    * Define InputStreams to read from the URLConnection.
                    */
                   InputStream is = ucon.getInputStream();
                   BufferedInputStream bis = new BufferedInputStream(is);

                   /*
                    * Read bytes to the Buffer until there is nothing more to read(-1).
                    */
                   ByteArrayBuffer baf = new ByteArrayBuffer(5000);
                   int current = 0;
                   while ((current = bis.read()) != -1) {
                      baf.append((byte) current);
                   }


                   /* Convert the Bytes read to a String. */
                   FileOutputStream fos = new FileOutputStream(file);
                   fos.write(baf.toByteArray());
                   fos.flush();
                   fos.close();
                   LoginActivity.statsofdownload++;

                   Log.d("DownloadManager","file://"+file.getAbsolutePath());

           } catch (IOException e) {
               Imageurl.pagestat="space";
               Log.d("DownloadManager", "Error: " + e);
           }

        }




myfunction()
{
 for(String string : Imageurl.output) {
                            imagea++;
                        final   int ind =imagea;
                        final String ss=string;
                        new Thread(new Runnable() {
                                public void run() {
                                      DownloadFromUrl(ss,"IMAGE"+ind+".jpeg");
                                      File root = android.os.Environment.getExternalStorageDirectory();         




                                   Imageurl.newyearsvalues.add("file://"+root.getAbsolutePath() + "/"+Imageurl.facebookpage+ "/"+"IMAGE"+ind+".jpeg");

                              }
                                }).start();


                    }

//// now need to call an activity but how I will know that these thread all end
}
4

3 回答 3

2

备选方案 1ExecutorServiceshutdown()和一起使用awaitTermination()

ExecutorService taskExecutor = Executors.newFixedThreadPool(noOfParallelThreads);
while(...) {
  taskExecutor.execute(new downloadImage());
}
taskExecutor.shutdown();
try {
  taskExecutor.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
} catch (InterruptedException e) {
  ...
}

基本上,shutdown()它会停止ExecutorService接受任何更多的线程请求。 awaitTermination()等待直到ExecutorService完成所有线程的执行。

替代方案 2:使用CountDownLatch

CountDownLatch latch = new CountDownLatch(totalNumberOfImageDownloadTasks);
ExecutorService taskExecutor = Executors.newFixedThreadPool(noOfParallelThreads);
while(...) {
  taskExecutor.execute(new downloadImage());
}

try {
  latch.await();
} catch (InterruptedException E) {
   // handle
}

在你的 imageDowloader() 函数中添加一行:

latch.countDown();

这将在每次执行时将锁存器的值增加 1。

于 2013-04-10T20:18:01.560 回答
1

您可能希望使用单个ThreadPoolExecutorexecute方法,而不是为每个可运行对象创建一个新线程,这样您就可以在线程完成工作后重用它们。

至于确定您的线程何时完成,请使用静态ConcurrentLinkedQueue跟踪成功完成,并使用另一个静态 ConcurrentLinkedQueue 跟踪可能需要重试的不成功完成。然后在您的 run() 方法中,您将包含代码

public void run() {
    try {
        ...
        successfulCompletionQueue.offer(this);
    } catch (Exception ex) {
        unsuccessfulCompletionQueue.offer(this);
    }
}

this与手头任务相关的任何日志信息在哪里。

于 2013-04-10T19:22:39.177 回答
1

要确定完成,使用asynctaskonPostExceute()方法,您可以确保所有图像都已下载,如果您需要进行下载以在下载时使用图像,您也可以查看进度。

由于onPostExecute()方法在ui线程中运行,现在应该没有任何问题。

但请记住asynctask,不能多次执行相同的操作。在这种情况下,您有 2 个选择:

  1. 下载所有图像asynctastask并从其更新活动onPostExecute()
  2. asynctask为每个下载单独执行。并使用每个onPostExecute()来更新活动。
于 2013-04-10T19:23:35.900 回答