美文网首页
多线程的认识

多线程的认识

作者: dev晴天 | 来源:发表于2018-08-11 19:01 被阅读0次
     一、 原理:
    1 不是说多线程开的越多越快。(手机迅雷 建议3-4个)
    2 还受服务器带宽的影响。
    3 可以理解为更多的cpu资源给了你(司马光砸缸多砸了几个口)
    
    二 、 分析 把服务器的文件资源等分 客户端 分别下载每一小快 一起进行
    1 获得服务器文件大小
    
    2 在客户端创建大小和服务器端一样的文件(提前申请好空间)
    
    2.1 每个线程下载的开始结束位置 记录
    
    3 开多个线程下载文件
    
    4 知道每个线程什么时候下载完毕
    
    
    三、补充:随机访问文件(RandomAccessFile类)
    此类的事例支持对随机访问文件的读取写入
    
     1、构造函数:
    RandomAccessFile(File file,String mode)
    
    mode可以为:r rw rws(包含元数据) rwd
    
    RandomAccessFile(String name,String mode)
    
    2、 一些方法:
     read()
     write()
     setLength() 设置此文件的长度
     seek(long pos) 设置指针偏移量 (达到每个线程从自己的位置开始)
    
    
    
    Demo:
    
    package com.example.administrator.httpclientdemo;
    
    import android.support.v7.app.AppCompatActivity;
    import android.os.Bundle;
    import android.util.Log;
    import android.view.View;
    import android.widget.Button;
    
    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 javax.net.ssl.HttpsURLConnection;
    
    public class MainActivity extends AppCompatActivity {
    
       // private static String PATH = "http://xiazai.sogou.com/comm/redir?softdown=1&u=0Gd8piB609380vCOL7GwJe7o9WVvkHDRKoqPuf-gGiXUWLXBAm9x94tIfhLGrwKWYNK-LbFKNWlpNfJyk0ESHL8iE21YxdYX&pcid=-3080605666447722537&filename=QQ_Setup.exe&w=1907&stamp=20171204";//要下载文件的路径
    
        private static String PATH="http://192.168.56.1/Demo/girls.jpg";
        private static int ThreadCount = 3;//假设开启三个线程
        private Button btnMutilDownload;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            initUI();//初始化ui
        }
    
        private void initUI() {
            btnMutilDownload = (Button) findViewById(R.id.mutil_down_load);
            // 点击事件处理
            btnMutilDownload.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    // 下载逻辑
                    httpRequest();
                }
            });
        }
    
        private void httpRequest() {
            //开启线程处理耗时 逻辑
            new Thread(new Runnable() {
                @Override
                public void run() {
                    HttpURLConnection connection = null;
                    try {
                        URL url = new URL(PATH);
                        connection = (HttpURLConnection) url.openConnection();
    
                        connection.setRequestMethod("GET");
                        int code = connection.getResponseCode();
                        if (code == 200) {
                            // 请求成功  进行多线程下载的操作(四个步骤)
    
                            // 1 获取服务器返回文件的大小
                            int length = connection.getContentLength();
                            Log.d("TAG", "文件大小(字节) :" + length);
                            // 2 在客户端创建大小和服务器端一样的文件(提前申请好空间)
                            RandomAccessFile rafAccessFile = new RandomAccessFile(getCacheDir()+"gril.jpg", "rw");
                            rafAccessFile.setLength(length);
                            //计算每个线程下载的大小
                            int blockSize = length / ThreadCount;
    
                            for (int i = 0; i < ThreadCount; i++) {
                                int startIndex = i * blockSize;
                                int endIndex = (i + 1) * blockSize - 1;
                                // 特殊情况 最后一个线程
                                if (i == ThreadCount - 1) {
                                    endIndex = length - 1;
                                }
                                //  3 开启线程去服务器下载文件 循环三次 三个线程
                                     new DownLoadThread(startIndex,endIndex,i).start();
                            }
                        }
    
    
                    } catch (MalformedURLException e) {
                        e.printStackTrace();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }).start();
        }
    
        // 定义线程去服务器现在文件
        class DownLoadThread extends Thread {
            // 通过构造方法吧每个线程 下载的开始结束位置传进来
            private int startIndex;
            private int endIndex;
            private int ThreadId;
    
            public DownLoadThread(int startIndex, int endIndex, int ThreadId) {
                this.startIndex = startIndex;
                this.endIndex = endIndex;
                this.ThreadId = ThreadId;
            }
    
            @Override
            public void run() {
                //去服务器下载文件的逻辑
                HttpURLConnection connection = null;
                try {
                    URL url = new URL(PATH);
                    connection = (HttpURLConnection) url.openConnection();
                    connection.setConnectTimeout(5000);
                    connection.setRequestMethod("GET");
                    //  4 设置一个请求头Range(告诉服务器每个线程下载的开始结束位置)固定写法
                    connection.setRequestProperty("Range","bytes="+startIndex+"-"+endIndex);
    //设置分段下载的头信息。  Range:做分段数据请求用的
                    int code = connection.getResponseCode();
                   // 5 获得状态码
                    if (code == 206) {
                        RandomAccessFile raf = new RandomAccessFile(getCacheDir()+"gril.jpg", "rw");
                        raf.seek(startIndex);
                        InputStream in = connection.getInputStream();
                    //把数据写到文件中
                        int len=-1;
                        byte []buff = new byte[1024];
                        while((len=in.read())!=-1){
                            raf.write(buff,0,len);
                        }
                        raf.close();
                        Log.d("Tag", "下载完毕"+ThreadId);
                    }
                } catch (Exception e) {
                    e.prin tStackTrace();
                }
            }
    
        }
    }
    
    
    
    
    
    

    相关文章

      网友评论

          本文标题:多线程的认识

          本文链接:https://www.haomeiwen.com/subject/gyodbftx.html