麻豆小视频在线观看_中文黄色一级片_久久久成人精品_成片免费观看视频大全_午夜精品久久久久久久99热浪潮_成人一区二区三区四区

首頁 > 系統 > 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開發頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 国产精品三级a三级三级午夜 | 日本爽快片100色毛片视频 | fc2国产成人免费视频 | 欧美性生交大片 | 黄污网址 | 国产精品剧情一区二区在线观看 | 羞羞色网站 | 韩日黄色片 | 色av成人天堂桃色av | 欧美精品一区二区三区在线 | 99re久久最新地址获取 | 久久大陆 | 国产午夜精品一区二区三区四区 | 欧美成人二区 | 亚洲综合无码一区二区 | 国产精品久久久久久久久久了 | 日韩美香港a一级毛片 | 国产精品久久久久久久久久三级 | 91短视频在线免费观看 | 爱视频福利 | 免费毛片视频播放 | 欧美一区二区三区久久精品视 | 在线a免费观看 | 黄色特级一级片 | 亚洲国产精品久久久久制服红楼梦 | 久久成人精品视频 | 麻豆911| 狠狠干91 | 亚洲射情| 日本免费aaa观看 | 日韩欧美激情视频 | 中文字幕22页 | 一级在线观看 | 182tv成人福利视频免费看 | 久久精品a一级国产免视看成人 | 免费观看国产精品视频 | 91快色视频| 久久国产免费视频 | 亚洲情av | 日韩视频一区二区三区四区 | 最近日本电影hd免费观看 |