Pergunta

Codifiquei um aplicativo simples em Java que baixa imagens específicas de uma lista de links HTML fornecidos. Tudo estava funcionando bem até eu adicionar o recurso de ter que baixar uma lista de links HTML em vez de apenas um. Eu tive que implementar os métodos Wait () e Notify () que me forçaram a mudar um pouco a abordagem. Agora, os downloads funcionam bem, mas a GUI não atualiza enquanto o download estiver em andamento.

Eu faço o 1º tópico esperar de Html.java e notificá -lo no final de DownloadImages.java. Para isso, tive que invocar a classe ButtonPressed como um objeto, em vez de um thread, e é por isso que acho que minha GUI não atualizará.

Existe uma maneira de simplificar ou tornar o uso de threads mais eficiente no meu código?

Desde já, obrigado.

Aqui está o esqueleto do meu código:

/*Test.java*/
package my;

import java.util.logging.Level;
import java.util.logging.Logger;

public class Test extends javax.swing.JFrame {

    public static buttonPressed bp;
    public static boolean alldone;

    /** Creates new form Test */
    public Test() {
        initComponents();
    }

    public static class buttonPressed implements Runnable {

        Thread t1, t2;

        buttonPressed() {
            t1 = new Thread(this, "downloadAction");
            t1.start();
        }

        public void suspendThread() {
            System.out.println("suspended");
            alldone = false;
        }

        public synchronized void resumeThread() {
            System.out.println("resumed");
            alldone = true;
            notify();
        }

        public void run() {
            String[] len = new String[]{/*list of urls*/};

            for (int i = 0; i < len.length; i++) {
                System.out.println("going times: " + i);

                t2 = new Thread(new HTML(), "HTMLthread");
                t2.start();

                synchronized (this) {
                    while (!alldone) {
                        try {
                            wait();
                        } catch (InterruptedException ex) {
                            Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
                        }
                    }
                }
            }
        }
    }

    private void downloadActionPerformed(java.awt.event.ActionEvent evt) {
        bp = new buttonPressed();
        try {
            bp.t1.join();
        } catch (InterruptedException e) {
            System.out.println("Main Thread: interrupted");
        }
    }

    public static void main(String args[]) {
        java.awt.EventQueue.invokeLater(new Runnable() {

            public void run() {
                new Test().setVisible(true);
            }
        });
    }

    private javax.swing.JButton download;
    public static javax.swing.JProgressBar progress;
}

/*HTML.java*/
package my;

import java.util.ArrayList;

class HTML implements Runnable {
    private Thread t3;

    public HTML() {
        Test.bp.suspendThread();
    }

    public void run() {
        downloadHTML();
        ArrayList xyz = parseHTML();
        t3 = new Thread(new DownloadImages(xyz), "DownDecrypt");
        t3.start();
    }

    private void downloadHTML() {
        // Downloads the HTML file
    }

    private ArrayList parseHTML() {
        // Parses the HTML file and gets links to images
        return new ArrayList();
    }
}

/*DownloadImages.java*/
package my;

import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;

class DownloadImages implements Runnable {

    static int current = 0, previous = 0;
    static boolean speedFlag;
    ArrayList<String> links = new ArrayList<String>();
    private Thread t4;

    public DownloadImages(ArrayList param1) {
        this.links = param1;
        speedFlag = true;
    }

    public void run() {
        t4 = new Thread(new getSpeed(), "getSpeed");
        t4.start();
        download(links);
    }

    private void download(ArrayList<String> param1) {
        String[] imgurl = new String[param1.size()];
        URLConnection conn = null;
        InputStream is = null;
        ByteArrayOutputStream bais = null;
        int prog;

        for (int i = 0; i < param1.size(); i++) {
            current = 0;
            imgurl[i] = param1.get(i);
            try {
                conn = new URL(imgurl[i]).openConnection();
                int fsize = conn.getContentLength();
                is = new BufferedInputStream(conn.getInputStream());
                bais = new ByteArrayOutputStream();

                byte[] byteChunk = new byte[1024];
                int n;
                while ((n = is.read(byteChunk)) > 0) {
                    bais.write(byteChunk, 0, n);
                    current = current + 1024;
                    prog = (int) (current * 100.0 / fsize);
                    Test.progress.setValue(prog);
                }
            } catch (MalformedURLException ex) {
                Logger.getLogger(DownloadImages.class.getName()).log(Level.SEVERE, null, ex);
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                if (is != null) {
                    try {
                        is.close();
                    } catch (IOException ex) {
                        Logger.getLogger(DownloadImages.class.getName()).log(Level.SEVERE, null, ex);
                    }
                }
            }

            byte[] imgBytes = bais.toByteArray();

            try {
                FileOutputStream fos = new FileOutputStream(i + ".jpg");
                fos.write(imgBytes);
                fos.flush();
                fos.close();
            } catch (FileNotFoundException ex) {
                System.out.println("FileNotFoundException : " + ex);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        speedFlag = false;
        // Resume the thread to start downloading the next link
        Test.bp.resumeThread();
    }

    private static class getSpeed implements Runnable {

        int kbytesPerSecond;
        private final int fireTime;

        public getSpeed() {
            fireTime = 1000;
        }

        public void run() {
            while (speedFlag) {
                try {
                    Thread.sleep(fireTime);
                } catch (InterruptedException ex) {
                    Logger.getLogger(getSpeed.class.getName()).log(Level.SEVERE, null, ex);
                }

                kbytesPerSecond = (((current - previous) / 1024) / (fireTime / 1000));
                System.out.println(kbytesPerSecond);

                previous = current;
            }
        }
    }
}
Foi útil?

Solução

No que diz respeito à GUI, você precisa ler sobre Concorrência de balanço. Em suma, use Swingworker.

Lembre -se de que você usa coisas antigas awt (java.awt.eventqueue).

Outras dicas

Sugiro que você tenha um executores como executores.newcachedthreadpool e envie () as tarefas. Colete os objetos futuros para saber quando eles terminarem. Isso será mais eficiente e gerenciável do que criar threads em todo o lugar.

Você pode ter apenas uma piscina como

static final ExecutorService POOL = Executors.newCachedThreadPool();

Para enviar uma tarefa

POOL.submit(new Callable<Void>() {
    public Void call() throws InterruptedException {
        while (speedFlag) {
            Thread.sleep(1000);

            kbytesPerSecond = (current - previous) / 1024;
            System.out.println(kbytesPerSecond);

            previous = current;
        }
    }
});

Ainda melhor para repetir tarefas é usar um serviço de executor programado.

static final ScheduledExecutorService POOL  = Executors.newScheduledThreadPool(4);
Future task = POOL.scheduleAtFixedRate(new Runnable() {
    public void run()  {
        kbytesPerSecond = (current - previous) / 1024;
        System.out.println(kbytesPerSecond);
        previous = current;
    }
}, 1, 1, TimeUnit.SECONDS);
// to end the task
task.cancel(false);
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top