新手 android 多线程



 package com.payne.xiazai;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.URL;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.text.TextUtils;
import android.view.View;
import android.widget.EditText;
import android.widget.ProgressBar;
import android.widget.Toast;

public class MainActivity extends Activity {
    protected static final int DOWN_LOAD_ERROR = 1;
    protected static final int SERVER_ERROR = 2;
    public static int threadCount = 3;
    public static int runningThread = 3;
    private EditText et_path;
    private ProgressBar pb;

    private Handler handler=new Handler(){
        public void handleMessage(Message msg) {
            switch (msg.what) {
            case DOWN_LOAD_ERROR:
                Toast.makeText(getApplicationContext(),"下载失败", Toast.LENGTH_SHORT).show();

                break;
            case SERVER_ERROR:
                Toast.makeText(getApplicationContext(),"服务器错误,下载失败", Toast.LENGTH_SHORT).show();

                break;
            }
        };
    };


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        et_path=(EditText)this.findViewById(R.id.editText1);
        pb=(ProgressBar) findViewById(R.id.progressBar1);
    }
    public void click(View view){
        final String path=et_path.getText().toString().trim();
        if(TextUtils.isEmpty(path)){
            Toast.makeText(this,"下载路径错误",Toast.LENGTH_SHORT).show();
            return;
        }

        new Thread(){
            public void run() {

                try {
                    //String path = "http://127.0.0.1:8080/setup.exe";
                    URL url = new URL(path);
                    HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                    conn.setConnectTimeout(5000);
                    conn.setRequestMethod("GET");
                    int code = conn.getResponseCode();
                    if (code == 200) {
                        int length = conn.getContentLength();
                        System.out.println("文件中长度" + length);
                        // 在客户端本地创建出来一个跟服务器端文件一样大小的临时文件
                        RandomAccessFile raf = new RandomAccessFile("/sdcard/setup.exe", "rwd");
                        // 指定创建这个文件的长度
                        raf.setLength(length);
                        raf.close();
                        // 假设是3个线程去下载资源
                        // 平均每个线程下载的文件大小
                        int blockSize = length / threadCount;
                        for (int threadId = 1; threadId <= threadCount; threadId++) {
                            // 下载的开始位置
                            int startIndex = (threadId - 1) * blockSize;
                            // 下载的结束位置
                            int endIndex = (threadId * blockSize) - 1;
                            if (threadId == threadCount) {
                                // 最后一个线程下载的位置
                                endIndex = length;
                            }
                            System.out.println("线程:" + threadId + "下载:----" + startIndex
                                    + "--->" + endIndex);
                            new DownlodThread(startIndex, endIndex, threadId, path).start();
                        }


                    } else {
                        System.out.println("服务器错误");
                        Message msg=new Message();
                        msg.what=SERVER_ERROR;
                        handler.sendMessage(msg);
                    }
                }catch (IOException e) {
                    e.printStackTrace();
                    Message msg=new Message();
                    msg.what=DOWN_LOAD_ERROR;
                    handler.sendMessage(msg);
                }


            };
        }.start();


    }

    /**
     * 下载文件的子线程 每一个线程下载对应位置的文件
     * 
     * @author Payne
     *
     */

    public class DownlodThread extends Thread {
        private int startIndex;
        private int endIndex;
        private int threadId;
        private String path;

        public DownlodThread(int startIndex, int endIndex, int threadId,
                String path) {
            super();
            this.startIndex = startIndex;
            this.endIndex = endIndex;
            this.threadId = threadId;
            this.path = path;
        }

        @Override
        public void run() {
            // TODO Auto-generated method stub
            try {
                File temp = new File("/sdcard/"+threadId + ".txt");
                if (temp.exists() && temp.length() > 0) {
                    FileInputStream fis = new FileInputStream(temp);
                    byte[] tempBytes = new byte[1024];
                    int leng = fis.read(tempBytes);
                    String downloadLen = new String(tempBytes, 0, leng);
                    int downloadInt = Integer.parseInt(downloadLen);
                    startIndex = downloadInt;
                    fis.close();
                }
                URL url = new URL(path);
                HttpURLConnection conn = (HttpURLConnection) url
                        .openConnection();
                conn.setReadTimeout(5000);
                conn.setRequestMethod("GET");
                // 重要:请求服务器下载部分的文件 指定文件的位置
                conn.setRequestProperty("Range", "bytes=" + startIndex + "-"
                        + endIndex);
                System.out.println("真实线程:" + threadId + "<---" + startIndex
                        + "--->" + endIndex);
                int code = conn.getResponseCode();// 从服务器请求全部资源200 ok
                                                    // 如果从服务器返回部分资源206 ok
                //System.out.println("code:" + code);
                if (code == 206) {
                    InputStream is = conn.getInputStream();// 已经设置了请求的位置
                                                            // 返回的是当前位置对应的文件的输入流
                    RandomAccessFile raf = new RandomAccessFile("/sdcard/setup.exe",
                            "rwd");
                    // 随机写文件的时候从那个位置开始写
                    raf.seek(startIndex);// 定位线程
                    int len = 0;
                    int total = 0;
                    byte[] buffer = new byte[1024];
                    while ((len = is.read(buffer)) != -1) {
                        RandomAccessFile file = new RandomAccessFile("/sdcard/"+threadId
                                + ".txt", "rwd");
                        raf.write(buffer, 0, len);
                        total += len;
                        //System.out.println("线程:" + threadId + "total" + total);
                        file.write((startIndex + total + "").getBytes());
                        file.close();

                    }
                    is.close();
                    raf.close();
                    System.out.println("线程:" + threadId + "下载完毕!");
                } else {
                    System.out.println("线程:" + threadId + "下载失败");
                }




            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }finally{
                runningThread--;
                if(runningThread==0){//所以线程已经执行完毕
                    for(int i=1;i<=3;i++){
                        File file=new File("/sdcard/"+i+".txt");
                        file.delete();
                    }
                    System.out.println("所以下载记录已经被清除");
                }
            }
        }

    }


}

logcat


 04-19 19:42:02.422: E/SoundPool(1272): error loading /system/media/audio/ui/Effect_Tick.ogg
04-19 19:42:02.422: W/AudioService(1272): Soundpool could not load file: /system/media/audio/ui/Effect_Tick.ogg
04-19 19:42:02.422: E/SoundPool(1272): error loading /system/media/audio/ui/Effect_Tick.ogg
04-19 19:42:02.422: W/AudioService(1272): Soundpool could not load file: /system/media/audio/ui/Effect_Tick.ogg
04-19 19:42:02.422: E/SoundPool(1272): error loading /system/media/audio/ui/Effect_Tick.ogg
04-19 19:42:02.422: W/AudioService(1272): Soundpool could not load file: /system/media/audio/ui/Effect_Tick.ogg
04-19 19:42:02.422: E/SoundPool(1272): error loading /system/media/audio/ui/Effect_Tick.ogg
04-19 19:42:02.422: W/AudioService(1272): Soundpool could not load file: /system/media/audio/ui/Effect_Tick.ogg
04-19 19:42:02.422: E/SoundPool(1272): error loading /system/media/audio/ui/Effect_Tick.ogg
04-19 19:42:02.422: W/AudioService(1272): Soundpool could not load file: /system/media/audio/ui/Effect_Tick.ogg
04-19 19:42:02.422: E/SoundPool(1272): error loading /system/media/audio/ui/KeypressStandard.ogg
04-19 19:42:02.422: W/AudioService(1272): Soundpool could not load file: /system/media/audio/ui/KeypressStandard.ogg
04-19 19:42:02.422: E/SoundPool(1272): error loading /system/media/audio/ui/KeypressSpacebar.ogg
04-19 19:42:02.422: W/AudioService(1272): Soundpool could not load file: /system/media/audio/ui/KeypressSpacebar.ogg
04-19 19:42:02.422: E/SoundPool(1272): error loading /system/media/audio/ui/KeypressDelete.ogg
04-19 19:42:02.422: W/AudioService(1272): Soundpool could not load file: /system/media/audio/ui/KeypressDelete.ogg
04-19 19:42:02.422: E/SoundPool(1272): error loading /system/media/audio/ui/KeypressReturn.ogg
04-19 19:42:02.422: W/AudioService(1272): Soundpool could not load file: /system/media/audio/ui/KeypressReturn.ogg
04-19 19:42:02.422: E/SoundPool(1272): error loading /system/media/audio/ui/KeypressInvalid.ogg
04-19 19:42:02.422: W/AudioService(1272): Soundpool could not load file: /system/media/audio/ui/KeypressInvalid.ogg
04-19 19:42:02.422: W/AudioService(1272): onLoadSoundEffects(), Error -1 while loading samples
04-19 19:42:02.432: W/System.err(7536): java.net.ConnectException: failed to connect to /127.0.0.1 (port 8080) after 5000ms: isConnected failed: ECONNREFUSED (Connection refused)
04-19 19:42:02.432: W/System.err(7536):     at libcore.io.IoBridge.isConnected(IoBridge.java:223)
04-19 19:42:02.432: W/System.err(7536):     at libcore.io.IoBridge.connectErrno(IoBridge.java:161)
04-19 19:42:02.432: W/System.err(7536):     at libcore.io.IoBridge.connect(IoBridge.java:112)
04-19 19:42:02.432: W/System.err(7536):     at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:192)
04-19 19:42:02.432: W/System.err(7536):     at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:459)
04-19 19:42:02.432: W/System.err(7536):     at java.net.Socket.connect(Socket.java:843)
04-19 19:42:02.432: W/System.err(7536):     at com.android.okhttp.internal.Platform.connectSocket(Platform.java:131)
04-19 19:42:02.462: W/System.err(7536):     at com.android.okhttp.Connection.connect(Connection.java:101)
04-19 19:42:02.462: W/System.err(7536):     at com.android.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:294)
04-19 19:42:02.462: W/System.err(7536):     at com.android.okhttp.internal.http.HttpEngine.sendSocketRequest(HttpEngine.java:255)
04-19 19:42:02.462: W/System.err(7536):     at com.android.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:206)
04-19 19:42:02.462: W/System.err(7536):     at com.android.okhttp.internal.http.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:345)
04-19 19:42:02.462: W/System.err(7536):     at com.android.okhttp.internal.http.HttpURLConnectionImpl.getResponse(HttpURLConnectionImpl.java:296)
04-19 19:42:02.462: W/System.err(7536):     at com.android.okhttp.internal.http.HttpURLConnectionImpl.getResponseCode(HttpURLConnectionImpl.java:503)
04-19 19:42:02.462: W/System.err(7536):     at com.payne.xiazai.MainActivity$2.run(MainActivity.java:73)
04-19 19:42:02.462: W/System.err(7536): Caused by: libcore.io.ErrnoException: isConnected failed: ECONNREFUSED (Connection refused)
04-19 19:42:02.462: W/System.err(7536):     at libcore.io.IoBridge.isConnected(IoBridge.java:208)
04-19 19:42:02.462: W/System.err(7536):     ... 14 more
04-19 19:42:02.612: I/Choreographer(1272): Skipped 32 frames!  The application may be doing too much work on its main thread.
04-19 19:42:02.672: I/Choreographer(1272): Skipped 34 frames!  The application may be doing too much work on its main thread.
04-19 19:42:58.203: I/Choreographer(1272): Skipped 40 frames!  The application may be doing too much work on its main thread.
04-19 19:45:01.005: D/ConnectivityService(1272): Sampling interval elapsed, updating statistics ..
04-19 19:45:01.005: D/ConnectivityService(1272): Done.
04-19 19:45:01.005: D/ConnectivityService(1272): Setting timer for 720seconds
04-19 19:55:02.074: D/dalvikvm(1272): GC_FOR_ALLOC freed 610K, 17% free 5670K/6768K, paused 13ms, total 16ms
04-19 20:00:01.008: D/ConnectivityService(1272): Sampling interval elapsed, updating statistics ..
04-19 20:00:01.008: D/ConnectivityService(1272): Done.
04-19 20:00:01.008: D/ConnectivityService(1272): Setting timer for 720seconds

请问这是什么原因呢

Android 多线程

萝莉的内裤 9 years, 10 months ago

04-19 19:42:02.432: W/System.err(7536): java.net.ConnectException: failed to connect to /127.0.0.1 (port 8080) after 5000ms: isConnected failed: ECONNREFUSED (Connection refused)

应该是127.0.0.1这个地址不对。你如果在模拟器上运行,手机的默认地址应该是10.0.2.3,和你的电脑不在一个网段,需要把模拟器的dns设置成电脑的IP地址,这样,你在程序中写电脑的IP才能正确连接(或者你可以尝试使用10.0.2.2进行连接,这个特殊的地址可以帮助模拟器连接本地PC),而且如果电脑可以上网的话,模拟器也可以上网。

莉子_提不起劲 answered 9 years, 10 months ago

127.0.0.1 这个地址是指向本地。
你手机的本地就是你手机的本身而不是电脑,你本来的意思,我猜是从你电脑下载某个文件,但是你的代码写的是从手机里下载某个文件,手机没有开启HTTP服务,当然就报错了~

musicat answered 9 years, 10 months ago

Your Answer