Условие завершения для потоков в Java - PullRequest
1 голос
/ 26 августа 2011

Я написал многопоточное Java-приложение, которое считывает кучу файлов .jar из каталога.Это приложение порождает несколько потоков, и каждый поток читает кучу файлов JAR.У меня проблемы с определением условия остановки для этого приложения.Как я могу определить, что все файлы были прочитаны?

Ниже приведена функция фрагмента, которая вызывается из метода run () для каждого потока.

    import java.io.*;
import java.util.Enumeration;
import java.util.jar.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipException;
import java.io.FilenameFilter;

public class ArchiveFileTest implements Runnable {
     private static boolean stopAll = false;
     private static int threadNumber = 0;
     private int myNumber = 0;

     public ArchiveFileTest () {
            myNumber = threadNumber;
            threadNumber++;
     }

     public static boolean setStopAll () {
            return setStopAll(true);
     }

     public static boolean setStopAll (boolean b) {
            stopAll = b;
            return stopAll;
     }

     public static String[] listFiles (File parentDir,final String ext1,final String ext2,final String ext3,final String ext4) {
            String allFiles[] = parentDir.list(new FilenameFilter() { 
                 public boolean accept(File pDir, String fName) {
                        if (fName.endsWith("."+ext1) || fName.endsWith("."+ext2) || fName.endsWith("."+ext3) || fName.endsWith("."+ext4)) return true;
                        else return false;
                 }
            });
            for (int i=0; i<allFiles.length; i++)
                 allFiles[i] = parentDir.getAbsolutePath() + File.separator +  allFiles[i];
            return allFiles;
     }

     public ZipFile getMyZipFile (File parentDir) {
            String fn[] = listFiles(parentDir, "jar", "zip", "war", "rar");
            int fileNum = myNumber % fn.length;
            ZipFile zFile = null;
            for (int i=0; i<fn.length; i++) {
                 String jFile = fn[(fileNum + i)%fn.length];
                 try {
                        zFile = new ZipFile(jFile);
                        break;
                 } catch  (IOException e) {
                     setStopAll();
                 }
            }
            return zFile;
     }

     public void doStuff() throws Exception {
            File dName = new File("/home/sqatest/chander/sample-files");
          final int N_TIMES = 15;
            final int N_FILES = 500;
          int counter = 0;
            int fCount  = 0;
            if (!dName.isDirectory() || !dName.exists()) {
                 System.err.println("The parent directory given should point to an existing directory...");
                 setStopAll();
                 return;
            }
          while (counter < N_TIMES) { 
                 ZipFile zipFile = getMyZipFile(dName);
                 if (zipFile == null) {
                        System.err.println("No zip file entry for the Thread-" + myNumber);
                        break;
                 }
                 try {
                        Enumeration <? extends ZipEntry> zipEntries = zipFile.entries(); 
                        fCount = 0;
                        ZipEntry ze = null;
                        while (zipEntries.hasMoreElements()) {
                             ze = zipEntries.nextElement();

                             if (ze.isDirectory()) continue; // if it is a directory go to next entry

                             InputStream is = zipFile.getInputStream(ze); 
                             fCount++;
                             int readCount = 0;
                             try {
                                    while(is.read((new byte[50])) != -1 && readCount != 200) readCount++;
                                    System.out.println("Successfully Read " + zipFile.toString());

                                    //is.close();
                             } catch (IOException e) {
                                    e.printStackTrace();
                             }
                             if (fCount == N_FILES) break;  // read maximum of N_FILES
                        }
                        if (stopAll) break;
                 } catch (Exception e) {
                     e.printStackTrace();
                 } finally {
                        counter++; 
                 }
          } 
     }

     public void run () {
            try {
                 doStuff();
            } catch (IOException e) {
                 e.printStackTrace();
                 setStopAll();
            } catch (Exception e) {
                 e.printStackTrace();
            }
     }

     public static void main (String[] args) throws Exception { 
          final int MAX_THREADS = 500;
          final int MAX_HOLDING_THREADS = 5;
            int loopCount = 0;
            Thread mainThread = Thread.currentThread();
            for (int m=0; ; m++) {
                 Thread t[] = new Thread[MAX_HOLDING_THREADS];
                 for (int n=0; n<t.length; n++) {
                        t[n] = new Thread(new ArchiveFileTest());
                        t[n].start();
                        if ((m+1)*(n+1)==MAX_THREADS) {
                             System.out.println("\n" + MAX_THREADS + " reached... \nMain Sleeping for some mins..."); 
                             loopCount++;
                             try {
                                    t[n].join();
                                    System.out.println("\nMain is back... (" + loopCount + ")");
                             } catch (InterruptedException e) {
                                    e.printStackTrace();
                                    setStopAll();
                             }
                             m = 0;
                        }
                 }
            }
     }
}

Ответы [ 3 ]

1 голос
/ 26 августа 2011

Если под остановкой вы подразумеваете завершение, то приложение остановится, когда все потоки, не являющиеся особым случаем демона, будут завершены.

1 голос
/ 26 августа 2011

Не думаю, что ваше приложение когда-нибудь остановится.У вас есть бесконечный цикл в методе main:

for (int m=0; ; m++) {
    ....
}

Обратите внимание, что установка m=0 внутри тела не разорвет цикл, поэтому я думаю, что вы никогда не закончите, даже если у вас нетфайл.Затем он непрерывно читает все файлы zip / jar / war / rar в каталоге (выбор файла на основе вращающегося счетчика myNumber не очень удобен в обслуживании), но никогда не выходит из цикла.

Если выТребуется прочитать ZIP-файлы, используя несколько потоков, тогда я бы пошел по-другому.

  1. Создать набор файлов, на которые вы хотите посмотреть.
  2. Создать ThreadPoolExecutor для создания фиксированного пула из 5 потоков
  3. Выполните итерацию по набору файлов и создайте новый Runnable, который выполняет извлечение Zip (хотя я не совсем уверен, почему выпрочитайте первые 10000 байт записи ZIP, а затем ничего с этим не сделайте) и вызовите метод execute.При этом будет использоваться пул потоков для обработки 5 файлов одновременно.
  4. После отправки всех исполняемых файлов Используйте метод shutdown, который будет ожидать завершения всех отправленных задач и завершит работу пула потоков.
1 голос
/ 26 августа 2011
  1. В вашем классе, который запускает потоки, есть счетчик volatile для ваших запущенных потоков.
  2. В своем конструкторе потоков передайте ссылку на класс запуска.
  3. Иметь синхронизированный метод, позволяющий потокам уведомлять запускающий класс о том, что они сделаны.
  4. После создания и запуска потоков ожидайте, пока счетчик не станет 0;

    while(getRunningThreads() > 0) // getRunningThreads must be synchronized too
        Thread.sleep(500); // Check every half second.
    
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...