Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.0k views
in Technique[技术] by (71.8m points)

multithreading - download a file in java using multi threading

I'm working on a downloader similar to IDM, I hava read This post about it. and I have implement my first-steps of code.

Here is the Downloader Class's Code:

package download.manager;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.channels.ReadableByteChannel;
import java.util.logging.Level;
import java.util.logging.Logger;


public class Downloader implements Runnable{

    private String url;
    private int num;
    private long start;
    private long end;
    ReadableByteChannel rbc;

    public Downloader(String url, int num, long start, long end, ReadableByteChannel rbc) {
        this.url = url;
        this.num = num;
        this.start = start;
        this.end = end;
        this.rbc = rbc;
    }        

    @Override
    public void run() {
        download();
    }

    private void download(){
        try {
            System.out.println(num + " is executing");
            URL file = new URL(url);
            FileOutputStream stream = new FileOutputStream("tmp"+num);                        
            stream.getChannel().transferFrom(rbc, start, end);
        } catch (MalformedURLException ex) {
            Logger.getLogger(Downloader.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IOException ex) {
            Logger.getLogger(Downloader.class.getName()).log(Level.SEVERE, null, ex);
        }

    }

}

and this is my main function:

package download.manager;

import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.channels.Channels;
import java.nio.channels.ReadableByteChannel;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author Behzad
 */
public class DownloadManager {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {

        URL file = null;
        ReadableByteChannel rbc = null;
        try {                       
            String url = "http://dl1.video.varzesh3.com/video/clip93/12/video/havashi/top5_save_derby_dortmond.mp4";
            file = new URL(url);
            rbc = Channels.newChannel(file.openStream());
            int size = file.openConnection().getContentLength(); 
            ExecutorService pool = Executors.newFixedThreadPool(4);
            int partSize = size / 4;
            pool.submit(new Downloader(url, 1, 0, partSize, rbc));
            pool.submit(new Downloader(url, 2, partSize, partSize, rbc));
            pool.submit(new Downloader(url, 3, 2 * partSize, partSize, rbc));
            pool.submit(new Downloader(url, 4, 3 * partSize, partSize, rbc));            
            pool.shutdown();
            pool.awaitTermination(Long.MAX_VALUE, TimeUnit.MILLISECONDS);
        } catch (MalformedURLException | InterruptedException ex) {
            Logger.getLogger(DownloadManager.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IOException ex) {
            Logger.getLogger(DownloadManager.class.getName()).log(Level.SEVERE, null, ex);
        }



    }

}

but when I run this code the downloader downloads just first part of file. as you see in the picture

enter image description here

what should I do for this ?

Here is updated download method :

private void download(){
        try {
            System.out.println(num + " is executing");
            URL file = new URL(url);
            ReadableByteChannel rbc = Channels.newChannel(file.openStream());
            FileOutputStream stream = new FileOutputStream("tmp"+num);                        
            stream.getChannel().transferFrom(rbc, start, end);
        } catch (MalformedURLException ex) {
            Logger.getLogger(Downloader.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IOException ex) {
            Logger.getLogger(Downloader.class.getName()).log(Level.SEVERE, null, ex);
        }

    }
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

transferTo is thread safe so you can only call it from one thread at a time.

If you want to read multiple parts of a file at once, the server has to support this and you need a stream for each portion of the file you are downloading.

For information on how to read portions of a file

Downloading a portion of a File using HTTP Requests

Reading the first part of a file using HTTP


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

2.1m questions

2.1m answers

60 comments

57.0k users

...