JavaFX Download Manager - wielowątkowość

0

Chciałbym zrobić program do pobierania plików w JavieFX8 i zastanawiam się jak to zrobic.
Oczywiście lista pobieranych plików powinna być w główym oknie aplikacji. Nowe pobieranie jest dzięki formatce która wyskakuje po nacisnięciu odpowiedniego przycisku co nie jest specjalnie trudne.
Teraz zastawiam się co z samym pobieraniem. Oczywiście klasa Download gdzie w konstruktorze podaje odpowiednie parametry implementuje Runnable. I teraz zastawiam się jak to wszystko "ożenić".
W TableView powinieniem mieć liste pobieranych plików i przyciski do stopowania,wznawiania itp no i oczywiście progress bar.
Tutaj mam klasę Download:

 
public class Download  implements Runnable{
    private final URL url;
    private final boolean requiresAuthentication;
    private final String user;
    private final String password;
    private final File localFile;
    private static final int MAX_BUFFER_SIZE = 1024;
    private int size;
    private int downloaded;

    private int status;
    public static final int DOWNLOADING = 0;
    public static final int WATING = 1;
    public static final int PAUSED = 2;
    public static final int COMPLETE = 3;
    public static final int CANCELLED = 4;
    public static final int ERROR = 5;

    public Download(URL url, boolean requiresAuthentication, String user, String password, File localFile) {
        this.url = url;
        this.requiresAuthentication = requiresAuthentication;
        this.user = user;
        this.password = password;
        this.localFile = localFile;
        downloaded = 0;
    }

    public void beginDownload(){
        status = DOWNLOADING;
        Thread thread = new Thread(this);
        thread.start();
    }

    @Override
    public void run() {
        HttpURLConnection connection = null;
        InputStream inputStream = null;
        OutputStream outputStream = null;
        int responseStatus;
        try{
            connection = (HttpURLConnection)url.openConnection();
            if(requiresAuthentication){
                String userpass = user + ":" + password;
                String basicAuth = "Basic " + new String(Base64.getEncoder().encode(userpass.getBytes()));
                connection.setRequestProperty ("Authorization", basicAuth);
            }
            connection.setRequestProperty("Range",
                    "bytes=" + downloaded + "-");
            connection.connect();
            responseStatus = connection.getResponseCode();
            if(responseStatus/100 != 2){
                throw new ConnectionException();
            }
            int contentLength = connection.getContentLength();
            if (contentLength < 1) {
                throw new ConnectionException();
            }
            if (size == -1) {
                size = contentLength;
            }
            inputStream = connection.getInputStream();
            outputStream = new FileOutputStream(localFile,true);
            while(status == DOWNLOADING){
                byte[] buffer;
                if (size - downloaded > MAX_BUFFER_SIZE) {
                    buffer = new byte[MAX_BUFFER_SIZE];
                } else {
                    buffer = new byte[size - downloaded];
                }
                int read = inputStream.read(buffer);
                if (read == -1) {
                    break;
                }
                outputStream.write(buffer,0,read);
                downloaded += read;
            }
            if(status == DOWNLOADING){
                status = COMPLETE;
            }

        }catch (IOException | ConnectionException e){
                status = ERROR;
        }finally {
            try{
                if(inputStream != null) {
                    inputStream.close();
                }
                if( outputStream != null) {
                    outputStream.close();
                }
            }catch (IOException e){

            }
        }
    }



}

Teraz zastanawiam się gdzie tak naprawde powinieniem stworzyć nowy wątek oraz jak zmieniac statusy pobierania pliku przez GUI. Można by na przyklad zmieniac statusy pobierania za pomocą metod takich jak np.

 
pause(){
status = PAUSE:
}

Ale raczej nie byłoby to zbyt dobre...
Zastanawiam się czy nie warto może po prostu zamiast implementować runnable odziedziczyć po tasku...

2

No ja bym użył Future z Javy 1.8. Runnable traktuj jako interfejs funkcyjny więc raczej stworzyłbym osobną klasę, któ©a ma tylko metodę run zamiast mieszać wszystko w jednym GOD object.

1 użytkowników online, w tym zalogowanych: 0, gości: 1