亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 系統 > Android > 正文

Android線程池控制并發數多線程下載

2019-10-21 21:30:54
字體:
來源:轉載
供稿:網友

多線程下載并不是并發下載線程越多越好,因為當用戶開啟太多的并發線程之后,應用程序需要維護每條線程的開銷,線程同步的開銷。

這些開銷反而會導致下載速度降低。因此需要避免在代碼中直接開啟大量線程執行下載。

主要實現步奏:

1、定義一個DownUtil類,下載工作基本在此類完成,在構造器中初始化UI線程的Handler。用于子線程和UI線程傳遞下載進度值。

2、所有的下載任務都保存在LinkedList。在init()方法中開啟一個后臺線程,不斷地從LinkedList中取任務交給線程池中的空閑線程執行。

3、每當addTask方法添加一個任務,就向 mPoolThreadHandler發送條消息,就從任務隊列中取出一個任務交給線程池執行。這里使用了使用了Semaphore信號量,也就是說只有當一個任務執行完成之后,release()一個信號量,才能從LinkedList中取出一個任務再去執行,否則acquire()方法會一直阻塞線程,直到上一個任務完成。

public class DownUtil{ //定義下載資源的路徑 private String path; //指定下載文件的保存位置 private String targetFile; //定義下載文件的總大小 private int fileSize; //線程池 private ExecutorService mThreadPool; //線程數量 private static final int DEFAULT_THREAD_COUNT = 5; //任務隊列 private LinkedList<Runnable> mTasks; //后臺輪詢線程 private Thread mPoolThread; //后臺線程的handler private Handler mPoolThreadHandler; //UI線程的Handler private Handler mUIThreadHandler; //信號量 private Semaphore semaphore; private Semaphore mHandlerSemaphore = new Semaphore(0); //下載線程數量 private int threadNum; public DownUtil(String path , String targetFile , int threadNum , final ProgressBar bar) {  this.path = path;  this.targetFile = targetFile;  this.threadNum = threadNum;  init();  mUIThreadHandler = new Handler()  {   int sumSize = 0;   @Override   public void handleMessage(Message msg)   {    if (msg.what == 0x123)    {     int size = msg.getData().getInt("upper");     sumSize += size;     Log.d("sumSize" , sumSize + "");     bar.setProgress((int) (sumSize * 1.0 / fileSize * 100));    }   }  }; } private void init() {  mPoolThread = new Thread()  {   public void run()   {    Looper.prepare();    mPoolThreadHandler = new Handler()    {     public void handleMessage(Message msg)     {      if (msg.what == 0x111)      {       mThreadPool.execute(getTask());       try       {        semaphore.acquire();       }       catch (InterruptedException e)       {        e.printStackTrace();       }      }     }    };    mHandlerSemaphore.release();    Looper.loop();   }  };  mPoolThread.start();  mThreadPool = Executors.newFixedThreadPool(DEFAULT_THREAD_COUNT);  mTasks = new LinkedList<>();  semaphore = new Semaphore(DEFAULT_THREAD_COUNT); } public void downLoad() {  try {   URL url = new URL(path);   HttpURLConnection conn = (HttpURLConnection) url.openConnection();   conn.setConnectTimeout(5 * 1000);   conn.setRequestMethod("GET");   conn.setRequestProperty(     "Accept",     "image/gif, image/jpeg, image/pjpeg, image/pjpeg, "       + "application/x-shockwave-flash, application/xaml+xml, "       + "application/vnd.ms-xpsdocument, application/x-ms-xbap, "       + "application/x-ms-application, application/vnd.ms-excel, "       + "application/vnd.ms-powerpoint, application/msword, */*");   conn.setRequestProperty("Accept-Language", "zh-CN");   conn.setRequestProperty("Charset", "UTF-8");   conn.setRequestProperty("Connection", "Keep-Alive");   //得到文件的大小   fileSize = conn.getContentLength();   conn.disconnect();   int currentPartSize = fileSize / threadNum + 1;   RandomAccessFile file = new RandomAccessFile(targetFile , "rw");   file.setLength(fileSize);   file.close();   for (int i = 0 ; i < threadNum ; i++)   {    //計算每條線程下載的開始位置    int startPos = i * currentPartSize;    //每條線程使用一個RandomAccessFile進行下載    RandomAccessFile currentPart = new RandomAccessFile(targetFile , "rw");    //定位該線程的下載位置    currentPart.seek(startPos);    //將任務添加到任務隊列中    addTask(new DownThread(startPos , currentPartSize , currentPart));   }  }  catch (IOException e)  {   e.printStackTrace();  } } private Runnable getTask() {  if (!mTasks.isEmpty())  {   return mTasks.removeFirst();  }  return null; } private synchronized void addTask(Runnable task) {  mTasks.add(task);  try  {   if (mPoolThreadHandler == null)   {    mHandlerSemaphore.acquire();   }  }  catch (InterruptedException e)  {   e.printStackTrace();  }  mPoolThreadHandler.sendEmptyMessage(0x111); } private class DownThread implements Runnable {  //當前線程的下載位置  private int startPos;  //定義當前線程負責下載的文件大小  private int currentPartSize;  //當前線程需要下載的文件塊  private RandomAccessFile currentPart;  //定義該線程已經下載的字節數  private int length;  public DownThread(int startPos , int currentPartSize , RandomAccessFile currentPart)  {   this.startPos = startPos;   this.currentPartSize = currentPartSize;   this.currentPart = currentPart;  }  @Override  public void run()  {   try   {    URL url = new URL(path);    HttpURLConnection conn = (HttpURLConnection) url.openConnection();    conn.setConnectTimeout(5 * 1000);    conn.setRequestMethod("GET");    conn.setRequestProperty(      "Accept",      "image/gif, image/jpeg, image/pjpeg, image/pjpeg, "        + "application/x-shockwave-flash, application/xaml+xml, "        + "application/vnd.ms-xpsdocument, application/x-ms-xbap, "        + "application/x-ms-application, application/vnd.ms-excel, "        + "application/vnd.ms-powerpoint, application/msword, */*");    conn.setRequestProperty("Accept-Language", "zh-CN");    conn.setRequestProperty("Charset", "UTF-8");    conn.setRequestProperty("Connection", "Keep-Alive");    InputStream inStream = conn.getInputStream();    //跳過startPos個字節    skipFully(inStream , this.startPos);    byte[] buffer = new byte[1024];    int hasRead = 0;    while (length < currentPartSize && (hasRead = inStream.read(buffer)) > 0)    {     currentPart.write(buffer , 0 , hasRead);     //累計該線程下載的總大小     length += hasRead;    }    Log.d("length" , length + "");    //創建消息    Message msg = new Message();    msg.what = 0x123;    Bundle bundle = new Bundle();    bundle.putInt("upper" , length);    msg.setData(bundle);    //向UI線程發送消息    mUIThreadHandler.sendMessage(msg);    semaphore.release();    currentPart.close();    inStream.close();   }   catch (Exception e)   {    e.printStackTrace();   }  } } public static void skipFully(InputStream in , long bytes) throws IOException {  long remaining = bytes;  long len = 0;  while (remaining > 0)  {   len = in.skip(remaining);   remaining -= len;  } }}

以下是MainActivity的代碼:

public class MainActivity extends Activity{ EditText url; EditText target; Button downBn; ProgressBar bar; DownUtil downUtil; private String savePath; @Override protected void onCreate(Bundle savedInstanceState) {  super.onCreate(savedInstanceState);  setContentView(R.layout.main);  //獲取界面中的四個界面控件  url = (EditText) findViewById(R.id.address);  target = (EditText) findViewById(R.id.target);  try  {   File sdCardDir = Environment.getExternalStorageDirectory();   savePath = sdCardDir.getCanonicalPath() + "/d.chm";  }  catch (Exception e)  {   e.printStackTrace();  }  target.setText(savePath);  downBn = (Button) findViewById(R.id.down);  bar = (ProgressBar) findViewById(R.id.bar);  downBn.setOnClickListener(new View.OnClickListener()  {   @Override   public void onClick(View view)   {    downUtil = new DownUtil(url.getText().toString() , target.getText().toString() , 7 , bar);    new Thread()    {     @Override     public void run()     {      try      {       downUtil.downLoad();      }      catch (Exception e)      {       e.printStackTrace();      }     }    }.start();   }  }); }}

頁面布局比較簡單這里一并貼出:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <TextView  android:layout_width="match_parent"  android:layout_height="wrap_content"  android:text="@string/title1"/> <EditText  android:id="@+id/address"  android:layout_width="match_parent"  android:layout_height="wrap_content"  android:text="@string/address"/> <TextView  android:layout_width="match_parent"  android:layout_height="wrap_content"  android:text="@string/targetAddress"/> <EditText  android:id="@+id/target"  android:layout_width="match_parent"  android:layout_height="wrap_content"/> <Button  android:id="@+id/down"  android:layout_width="match_parent"  android:layout_height="wrap_content"  android:text="@string/down"/> <!-- 定義一個水平進度條,用于顯示下載進度 --> <ProgressBar  android:id="@+id/bar"  android:layout_width="match_parent"  android:layout_height="wrap_content"  android:max="100"  style="?android:attr/progressBarStyleHorizontal"/></LinearLayout>

此例主要是在李剛老師的《瘋狂Java的講義》的多線程的例子上修改,感謝李剛老師,如有不足之處,歡迎批評指正。

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持VEVB武林網。


注:相關教程知識閱讀請移步到Android開發頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
亚洲第一精品福利| 日韩av大片免费看| 91精品久久久久久久久久久久久| 久久精品小视频| 在线视频欧美性高潮| 亚洲**2019国产| 青草成人免费视频| 欧美在线免费视频| 欧美日韩国产精品一区二区三区四区| 成人精品一区二区三区电影免费| 午夜免费日韩视频| 久色乳综合思思在线视频| 黑人巨大精品欧美一区二区免费| 精品国产一区二区三区在线观看| 亚洲国产另类 国产精品国产免费| 精品国产一区二区三区久久久| 亚洲欧洲一区二区三区在线观看| 欧美激情精品久久久久久久变态| 国产视频精品va久久久久久| 精品人伦一区二区三区蜜桃网站| 欧美性感美女h网站在线观看免费| 亚洲风情亚aⅴ在线发布| 国产97人人超碰caoprom| 91av在线播放| 日韩禁在线播放| 秋霞av国产精品一区| 国产成人一区二区三区小说| 久久精品视频网站| 久久久www成人免费精品| 国产精品男女猛烈高潮激情| 欧美大片va欧美在线播放| 成人黄色网免费| 麻豆国产va免费精品高清在线| 国产精品极品美女在线观看免费| 亚洲成人激情在线观看| 国内精品模特av私拍在线观看| 成人在线视频网| 久久午夜a级毛片| 国产成人综合av| 欧美日韩免费看| 成人妇女淫片aaaa视频| 懂色av一区二区三区| 亚洲成人亚洲激情| 中文字幕不卡在线视频极品| 日韩大片免费观看视频播放| 日韩av电影手机在线观看| 最新亚洲国产精品| 国产欧美一区二区三区视频| 亚洲精品国产电影| 国产午夜精品视频| 91热精品视频| 国产欧美一区二区三区在线| 日韩一区视频在线| 亚洲无限乱码一二三四麻| 亚洲色图美腿丝袜| 大胆欧美人体视频| 久久全球大尺度高清视频| 亚洲第一二三四五区| 中文字幕精品www乱入免费视频| 亚洲欧美国产日韩天堂区| 国模精品视频一区二区三区| 国产亚洲美女久久| 国产亚洲精品综合一区91| 日韩电影免费观看在线观看| 国产精品成人在线| 97超级碰碰人国产在线观看| 久久欧美在线电影| 欧美日韩色婷婷| 久久在线免费视频| 青青草成人在线| 亚洲桃花岛网站| 久久视频在线观看免费| 91美女高潮出水| 另类美女黄大片| 日韩高清电影免费观看完整版| 欧美日韩国产色| 亚洲欧美中文字幕在线一区| 成人黄色大片在线免费观看| 日韩在线视频免费观看| 日本精品性网站在线观看| 国产日韩欧美另类| 成人黄色片网站| 性亚洲最疯狂xxxx高清| 亚洲色图第三页| 久久久天堂国产精品女人| 欧美大片在线影院| 欧美激情亚洲国产| 国产精品一区二区久久| 欧美黄网免费在线观看| 色婷婷久久av| 日韩一区二区精品视频| 国产精品久久久久77777| 久久男人的天堂| 欧美日韩电影在线观看| 久久久爽爽爽美女图片| 欧美午夜激情小视频| 国产精品日韩欧美| 日韩免费观看高清| 久久精品视频99| 国产精品激情av电影在线观看| 国产精品揄拍一区二区| 亚洲变态欧美另类捆绑| 亚洲一区二区三区在线免费观看| 国产一区二区三区在线观看网站| 国产成+人+综合+亚洲欧美丁香花| 欧美成人黑人xx视频免费观看| 日韩欧美高清在线视频| 欧美极度另类性三渗透| 久久91精品国产| 成人午夜两性视频| 欧美激情va永久在线播放| 精品在线欧美视频| 国产a级全部精品| 91精品国产自产91精品| 日韩成人小视频| 国产一区二区在线免费视频| 97精品视频在线播放| 日韩一二三在线视频播| 亚洲性日韩精品一区二区| 91香蕉嫩草神马影院在线观看| 日韩动漫免费观看电视剧高清| 欧美成人sm免费视频| 国产精品永久免费在线| 久久99久久久久久久噜噜| 国产精品美女免费| 亚洲欧美综合另类中字| 国产精品久久久久久久久久| 欧美激情一级欧美精品| 亚洲成人精品av| 中文字幕日韩视频| 欧美最猛性xxxxx(亚洲精品)| 中文字幕欧美精品日韩中文字幕| 国产suv精品一区二区| 久久人体大胆视频| 欧美激情第99页| 在线看国产精品| 精品一区二区三区电影| 91久久久在线| 亚洲欧美日韩另类| 成人激情在线播放| 欧美亚洲视频在线看网址| 日本精品中文字幕| 欧美性猛交xxxx免费看漫画| 青青草原一区二区| 久久久久久久999| 日本精品久久久久影院| 91精品免费视频| 欧美成aaa人片免费看| 欧美日韩国产综合新一区| 日韩视频―中文字幕| 久久国产精品首页| 久久久久久久网站| 一区二区三区日韩在线| 爽爽爽爽爽爽爽成人免费观看| 午夜精品久久久久久99热| 日韩av在线网站| 欧美老妇交乱视频| 一本大道亚洲视频| 欧美理论电影在线播放| 国产精品69精品一区二区三区| 97精品国产aⅴ7777| 亚洲天堂av在线播放| 欧美成人精品在线播放| 日韩高清人体午夜|