Scusa ma non ho capito perchè si mette
executor.shutdown ();
executor.awaitTermination (Long.MAX_VALUE, TimeUnit.SECONDS);

quando appena sotto fai f.get??

f.get è bloccante cioè il programma si blocca finchè il metodo call non è terminato
dico giusto?? che serve aspettare che il thread future termini se già f.get poco sotto
fa già questa parte??

grazie mille

Roby

Originariamente inviato da andbin
Secondo me non va molto bene che sia il task ad estrarre dall'elenco (stack o lista che sia) il nome del file da trattare. Primo ci sono questioni di sincronizzazione, perché più thread devono accedere all'elenco. Ma poi se l'elenco è vuoto??

Io sfrutterei Callable/Future. Callable è più o meno simile ad un Runnable ma in più è in grado di restituire un valore e anche lanciare eccezioni. Quando invio un Callable ad un ExecutorService, mi ritorna un Future che rappresenta il "risultato" di una elaborazione asincrona.

Farei una classe, che implementa Callable, che riceve il nome del jar. Nel suo call() elabora il jar e poi ritorna un risultato.

Ecco un codice di esempio che ho scritto:

codice:
import java.io.*;
import java.util.*;
import java.util.concurrent.*;
import java.util.zip.*;

public class JarAnalyserApplication
{
    public static void main (String[] args)
    {
        analyze (Arrays.asList (args));
    }

    public static void analyze (List<String> filesList)
    {
        try
        {
            //---- creo la lista dei risultati ----
            List<Future<JarAnalyzerResult>> futures = new ArrayList<Future<JarAnalyzerResult>> ();

            //---- creo il thread-pool ----
            ExecutorService executor = Executors.newFixedThreadPool (20);

            //---- creo i task e li invio al thread-pool ----
            for (String file : filesList)
            {
                JarAnalyzerTask task = new JarAnalyzerTask (file);
                Future<JarAnalyzerResult> f = executor.submit (task);
                futures.add (f);
            }

            //---- attendo la fine della elaborazione ----
            executor.shutdown ();
            executor.awaitTermination (Long.MAX_VALUE, TimeUnit.SECONDS);

            //---- prelevo i risultati di ogni task ----
            for (Future<JarAnalyzerResult> f : futures)
            {
                JarAnalyzerResult result = f.get ();

                System.out.println ("jar file: " + result.getFilename ());

                Set<String> packagesSet = result.getPackages ();

                for (String pkg : packagesSet)
                    System.out.println ("   " + pkg);
            }
        }
        catch (ExecutionException ee)
        {
            System.out.println ("Il task ha lanciato la eccezione:");
            System.out.println (ee.getCause ());
        }
        catch (Exception e)
        {
            System.out.println (e);
        }
    }
}


class JarAnalyzerTask implements Callable<JarAnalyzerResult>
{
    private String jarFilename;

    public JarAnalyzerTask (String jarFilename)
    {
        this.jarFilename = jarFilename;
    }

    public JarAnalyzerResult call ()
        throws IOException
    {
        ZipFile zipFile = new ZipFile (jarFilename);

        Set<String> foldersSet = new HashSet<String> ();

        try
        {
            Enumeration<? extends ZipEntry> entriesEnum = zipFile.entries ();

            while (entriesEnum.hasMoreElements ())
            {
                ZipEntry zipEntry = entriesEnum.nextElement ();

                if (!zipEntry.isDirectory ())
                {
                    String entryName = zipEntry.getName ();

                    if (entryName.endsWith (".class"))
                    {
                        File entryFile = new File (entryName);

                        foldersSet.add (entryFile.getParent ());
                    }
                }
            }
        }
        finally
        {
            zipFile.close ();
        }

        TreeSet<String> packagesSet = new TreeSet<String> ();

        for (String folder : foldersSet)
            packagesSet.add (folder.replace (File.separator, "."));

        return new JarAnalyzerResult (jarFilename, packagesSet);
    }
}


class JarAnalyzerResult
{
    private String jarFilename;
    private Set<String> packagesSet;

    public JarAnalyzerResult (String jarFilename, Set<String> packagesSet)
    {
        this.jarFilename = jarFilename;
        this.packagesSet = packagesSet;
    }

    public String getFilename () { return jarFilename; }
    public Set<String> getPackages () { return packagesSet; }
}
Non è sicuramente perfetto ma può dare l'idea.