首页 > 安全资讯 >

android单线程,多线程下载

11-09-27

单线程下载很简单,就是开启一个线程去下载资源再进行本地保存;多线程下载是通过RandomAccessFile(随机文件读写操作类)来设置每个线程读取文件的起始点位置,起始点之间的长度即为该线程需要下载的文件大小下...

单线程下载很简单,就是开启一个线程去下载资源再进行本地保存;

多线程下载是通过RandomAccessFile(随机文件读写操作类)来设置每个线程读取文件的起始点位置,起始点之间的长度即为该线程需要下载的文件大小

下载开始位置:线程id*每条线程下载的数据长度 = ?

下载结束位置:(线程id+1)*每条线程下载的数据长度-1=?

这样比如文件大小:size,线程数:threads,则每个线程的下载量:size/threads;但是这是整除的情况,如果考虑到不能整除的情况:则前threads-1个线程下载量为size/threads,最后一个线程的下载量:size/threads+size%threads
File_downactivity.java代码 
package file.down; 
 
import java.io.File; 
import java.net.MalformedURLException; 
import java.net.URL; 
import java.net.URLConnection; 
 
import javax.security.auth.PrivateCredentialPermission; 
 
import android.R.integer; 
import android.app.Activity; 
import android.os.Bundle; 
import android.os.Handler; 
import android.util.Log; 
import android.view.View; 
import android.view.View.OnClickListener; 
import android.view.ViewDebug.FlagToString; 
import android.widget.Button; 
import android.widget.EditText; 
import android.widget.ProgressBar; 
import android.widget.TextView; 
 
public class File_downActivity extends Activity { 
    private Button but1,but2; 
    private EditText etUrl; 
    private ProgressBar bar1,bar2; 
    private TextView tv1,tv2; 
    private boolean flag = true; 
    private int temp = 0; 
    private int downLoadedSize = 0; 
    /** Called when the activity is first created. */ 
    @Override 
    public void onCreate(Bundle savedInstanceState) { 
        super.onCreate(savedInstanceState); 
        setContentView(R.layout.main); 
        etUrl = (EditText) findViewById(R.id.downloadUrl); 
         
        but1 = (Button) findViewById(R.id.but1); 
        but2 = (Button) findViewById(R.id.but2); 
         
        bar1 = (ProgressBar) findViewById(R.id.downloadProgressBar1); 
        bar2 = (ProgressBar) findViewById(R.id.downloadProgressBar2); 
         
        tv1 = (TextView) findViewById(R.id.tv1); 
        tv2 = (TextView) findViewById(R.id.tv2); 
         
         
        //单线程下载 
        but1.setOnClickListener(new OnClickListener() { 
             
            @Override 
            public void onClick(View v) { 
                if(DownUtil.isExistSdCard()){ 
                    if(DownUtil.checkNet(File_downActivity.this)){ 
                        if(DownUtil.creatDir(DownUtil.path1)){ 
                            thread.start(); 
                        } 
                    } 
                } 
            } 
        }); 
        //多线程下载 
        but2.setOnClickListener(new OnClickListener() { 
             
            @Override 
            public void onClick(View v) { 
                mulThread.start(); 
            } 
        }); 
    } 
    @Override 
    protected void onDestroy() { 
        super.onDestroy(); 
        DownUtil.downLoadSize = 0; 
    } 
    /** 
     * 单线程下载 
     */ 
    private Thread thread = new Thread(new Runnable() { 
         
        @Override 
        public void run() { 
                 
                DownUtil.fileDown1(etUrl.getText().toString(), DownUtil.savePath1, handler); 
                bar1.setMax(DownUtil.fileSize); 
        } 
    }); 
    /** 
     * 多线程下载(主线程类) 
     */ 
    private Thread mulThread = new Thread(new Runnable() { 
        private int blockSize,downLoadSizeMore; 
        private int threadNum = 5;//线程数 
         
        @Override 
        public void run() { 
//          MulDownThread[] threads = new MulDownThread[threadNum]; 
            try { 
                URL url = new URL(etUrl.getText().toString()); 
                URLConnection connection = url.openConnection(); 
                DownUtil.fileSize2 = connection.getContentLength(); 
                if(DownUtil.fileSize2 <= 0){ 
                    return; 
                } 
            } catch (Exception e) { 
                e.printStackTrace(); 
            } 
            //计算每个线程下载的数据量 
            blockSize = DownUtil.fileSize2 / threadNum; 
            //解决整除后余下的数据量 
            downLoadSizeMore = DownUtil.fileSize2 % threadNum; 
            bar2.setMax(100); 
            if(DownUtil.creatDir(DownUtil.path2)){ 
                 
                File file = new File(DownUtil.savePath2 + "/" + etUrl.getText().toString().substring(etUrl.getText().toString().lastIndexOf("/") + 1)); 
                for(int i=0;i<threadNum;i++){ 
                    if(i < threadNum - 1){ 
                         
                        //启动线程,分别下载文件 
                        MulDownThread thread = new MulDownThread(etUrl.getText().toString(), file, i*blockSize, (i + 1) * blockSize - 1,handler); 
                        thread.start(); 
                    }else{//最后那个线程下载的文件长度要等于每个线程平均下载量加上整除后的余数 
                        MulDownThread thread = new MulDownThread(etUrl.getText().toString(), file, i*blockSize, (i + 1) * blockSize - 1 + downLoadSizeMore,handler); 
                        thread.start(); 
                    } 
//                  //启动线程,分别下载文件 
//                  MulDownThread thread = new MulDownThread(etUrl.getText().toString(), file, i*blockSize, (i + 1) * blockSize -1); 
//                  thread.start(); 
//                  handler.sendEmptyMessage(10); 
                } 
//              boolean finished = false; 
//              while(!finished){ 
//                  //先把整除的余数搞定 
//                  downLoadedSize = downLoadSizeMore; 
//                  finished = true; 
//                  for(int i = 0;i<threads.length;i++){ 
//                      downLoadedSize += threads[i].downLoadSize; 
//                      if(!threads[i].isFinisthed){ 
//                          finished = false; 
//                      } 
//                  } 
//                  handler.sendEmptyMessage(10); 
//              } 
            } 
        } 
    }); 
    private Handler handler = new Handler(){ 
        public void handleMessage(android.os.Message msg) { 
            switch (msg.what) { 
            case 0: 
                tv1.setText("无法获取文件大小"); 
                break; 
            case -1: 
                tv1.setText("下载完成"); 
                bar1.setProgress(100); 
                but1.setClickable(false); 
                break; 
 
            case 1: 
                but1.setClickable(false); 
                int result = Double.valueOf(((Integer.parseInt(msg.obj.toString())*1.0 / DownUtil.fileSize * 100))).intValue(); 
                bar1.setProgress(result); 
                tv1.setText(result + "%"); 
                break; 
            case 2: 
                tv1.setText("文件获取错误"); 
                break; 
            case 10://多线程下载更新进度条 
                but2.setClickable(false); 
                int result2 = (Double 
                        .valueOf((Integer.parseInt(msg.obj.toString()) * 1.0 / DownUtil.fileSize2 * 100))) 
                        .intValue(); 
                bar2.setProgress(result2); 
                if(result2 == 100){ 
                    tv2.setText("下载完成"); 
                }else{ 
                     
                    tv2.setText(result2 + "%"); 
                } 
                break; 
            } 
        }; 
    }; 

 
Muldownthread.java代码 
package file.down; 
 
import java.io.File; 
 
import android.os.Handler; 
/** 
 * 线程类 
 * @author Administrator 
 * 
 */ 
public class MulDownThread extends Thread { 
 
    private String url; 
    private File file; 
    private int startPosition; 
    private int endPosition; 
    private Handler handler; 
     
     
    public MulDownThread(String url,File file,int startPosition,int endPosition,Handler handler){ 
        this.url = url; 
        this.file = file; 
        this.startPosition = startPosition; 
        this.endPosition = endPosition; 
        this.handler = handler; 
    } 
     
    @Override 
    public void run() { 
        DownUtil.fileDown2(url, file, startPosition, endPosition,handler); 
    } 
 
     
     

 
Downutil.java代码 
package file.down; 
 
import java.io.BufferedInputStream; 
import java.io.File; 
import java.io.FileInputStream; 
import java.io.FileNotFoundException; 
import java.io.FileOutputStream; 
import java.io.IOException; 
import java.io.InputStream; 
import java.io.RandomAccessFile; 
import java.net.HttpURLConnection; 
import java.net.MalformedURLException; 
import java.net.URL; 
import java.net.URLConnection; 
 
import android.R.integer; 
import android.R.string; 
import android.content.Context; 
import android.net.ConnectivityManager; 
import android.net.NetworkInfo; 
import android.os.Environment; 
import android.os.Handler; 
import android.os.Message; 
import android.util.Log; 
 
public class DownUtil { 
 
    //单线程下载目录 
    public static String path1 = "/down1/"; 
    public static String savePath1; 
    //多线程下载目录 
    public static String path2 = "/down2/"; 
    public static String savePath2; 
     
    public static String fileName; 
    public static int fileSize; 
    public static int fileSize2; 
     
    private static int curPosition; 
    //已下载的文件大小 
    public static int downLoadSize; 
    //标示当前线程是否下载完成 
    public static boolean finished = false; 
    /** 
     * 判断sd卡是否存在 
     * Environment.MEDIA_MOUNTED 判断SD卡是否存在 
     * @return 
     */ 
    public static boolean isExistSdCard(){ 
        boolean flag = true; 
        if(!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){ 
            flag = false; 
        } 
        return flag; 
    } 
    /** 
     * 创建目录 
     * @param dir 
     * @return 
     */ 
    public static boolean creatDir(String dir){ 
        boolean flag = false; 
        File file = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + dir); 
        if(!file.exists()){ 
            file.mkdir(); 
            if(file.exists()){ 
                flag = true; 
                savePath1 = file.getAbsolutePath(); 
                savePath2 = file.getAbsolutePath(); 
            } 
        }else{ 
            flag = true; 
            savePath1 = file.getAbsolutePath(); 
            savePath2 = file.getAbsolutePath(); 
        } 
        return flag; 
    } 
    /** 
     * 检查网络是否可用 
     * @return 
     */ 
    public static boolean checkNet(Context context){ 
        boolean flag = false; 
        ConnectivityManager manager = (ConnectivityManager) context.getSystemService(context.CONNECTIVITY_SERVICE); 
        NetworkInfo wifi = manager.getNetworkInfo(ConnectivityManager.TYPE_WIFI); 
        NetworkInfo mobile = manager.getNetworkInfo(ConnectivityManager.TYPE_MOBILE); 
        if(wifi.isConnectedOrConnecting() || mobile.isConnectedOrConnecting()){ 
            flag = true; 
        } 
        return flag; 
    } 
    /** 
     * 单线程文件下载 
     * @param url 
     * @param path 
     */ 
    public static void fileDown1(String url,String path,Handler handler) { 
        Log.v("=path=", path+"="); 
        Message message = new Message(); 
        if(!"".equals(url)){ 
            fileName = url.substring(url.lastIndexOf("/") + 1); 
            InputStream inputStream = null; 
            FileOutputStream outputStream = null; 
            try { 
                URL myuUrl = new URL(url); 
                URLConnection connection = myuUrl.openConnection(); 
                connection.connect(); 
                inputStream = connection.getInputStream(); 
                fileSize = connection.getContentLength(); 
                Log.v("=fileSize=", DownUtil.fileSize+"="); 
                if(fileSize <= 0){ 
                    message.what = 0; 
                    handler.sendMessage(message); 
                    return; 
                }else{ 
                    outputStream = new FileOutputStream(path +"/"+ fileName); 
                    //存储文件 
                    byte buf[] = new byte[inputStream.available()]; 
                    int len = 0; 
                    int temp = 0; 
                    Log.v("=available=", inputStream.available()+"="); 
                    while ((len = inputStream.read(buf)) != -1) { 
                        outputStream.write(buf, 0, len); 
                        temp += len; 
                        Message message2 = new Message(); 
                        message2.what = 1; 
                        message2.obj = temp;//下载的百分比 
                        handler.sendMessage(message2); 
                    } 
                    Message msg = new Message(); 
                    //通知下载完成 
                    msg.what = -1; 
                    handler.sendMessage(msg); 
                } 
            } catch (Exception e) { 
                message.what = 2; 
                handler.sendMessage(message); 
                return; 
            }finally{ 
                try { 
                     
                    if(inputStream != null || outputStream != null){ 
                        outputStream.close(); 
                        inputStream.close(); 
                    } 
                } catch (Exception e2) { 
                } 
            } 
        } 
    } 
    /** 
     * 多线程下载文件 
     * @param url 
     * @param path 
     * @param handler 
     */ 
    public static void fileDown2(String url,File file,int startPosition,int endPosition,Handler handler){ 
        URLConnection connection = null; 
        InputStream inputStream = null; 
        BufferedInputStream bis = null; 
        RandomAccessFile raf = null; 
        try { 
            URL url2 = new URL(url); 
            connection = url2.openConnection(); 
//          connection.connect(); 
            connection.setAllowUserInteraction(true); 
            // 设置当前线程下载的起点,终点 
            connection.setRequestProperty("Range", "bytes=" + startPosition + "-" 
                    + endPosition); 
            inputStream = connection.getInputStream(); 
            if(fileSize2 <= 0){ 
                return; 
            } 
            //对文件进行随机读写操作 
            raf = new RandomAccessFile(file,"rw"); 
            //设置开始写文件的位置 
            raf.seek(startPosition); 
            bis = new BufferedInputStream(inputStream); 
            //开始循环以流的形式读写文件 
//          curPosition = startPosition; 
            //每个线程需要读取文件的长度 
//          int temp = endPosition - startPosition; 
            byte[] buffer = new byte[1024]; 
            int length = 0; 
            while ((length = inputStream.read(buffer)) != -1) { 
                raf.write(buffer, 0, length); 
                downLoadSize += length; 
                Message message = new Message(); 
                message.what = 10; 
                message.obj = downLoadSize; 
                handler.sendMessage(message); 
            } 
//          while (curPosition < endPosition) { 
//              int len = bis.read(buffer, 0, temp); 
//              if(len == -1){ 
//                  break; 
//              } 
//              Log.v("=len=", "="+len); 
//              raf.write(buffer, 0, len); 
//              curPosition += len; 
////                if(curPosition > endPosition){ 
////                    downLoadSize += len - (curPosition - endPosition) + 1; 
////                    Log.v("=downLoadSize=", "="+downLoadSize); 
////                }else{ 
//                  downLoadSize += len; 
////                } 
//                  Message message = new Message(); 
//                  message.what = 10; 
//                  message.obj = downLoadSize; 
//                  handler.sendMessage(message); 
//          } 
        } catch (Exception e) { 
            e.printStackTrace(); 
        }finally{ 
            try { 
                if(inputStream != null || raf != null || bis != null){ 
                    bis.close(); 
                    raf.close(); 
                    inputStream.close(); 
                } 
            } catch (Exception e2) { 
            } 
        } 
    } 

作者“shufeipenglove-163-com”
 

相关文章
最新文章
热点推荐