public static void main(final String[] args) throws InterruptedException {
        // Einlesen Properties-Daten
        final Data data;
        // Name von Properties-File als Argument
        String nameOfPropertiesFile = "";

        // Argument könnte Name für Properties-File sein
        if (args.length > 0) {
            try {
                Integer.parseInt(args[0]);
            } catch (NumberFormatException e) {
                // Wenn Arg. ein String ist, als Filename interpretieren
                nameOfPropertiesFile = args[0];
            }
        }

        // Objekt erzeugen, Properties-Definitionen sowie Argumente prüfen
        data = new Data(nameOfPropertiesFile, args);

        // Prioritaet main-Thread festlegen
        Thread.currentThread().setPriority(data.getMainPriority());

        // Aktivitaet #1: Ausgabe Data (Parameter von Properties-File,
        // Argumente)
        data.printData();

        // Generate the store according properites definitions.
        Store store = new Store(data.getMinimalStoreSize(), data.getMaximalStoreSize(),
                data.getMonitorStoreIsFair());
        AbstractWorker.setStore(store);

        // Generate the global bookkeeper object
        Bookkeeper bookkeeper = new Bookkeeper();
        AbstractWorker.setBookkeeper(bookkeeper);
        // Generate the global information printer
        InfoPrinter printer = new InfoPrinter();
        AbstractWorker.setPrinter(printer);

        // Thread handling starten und Produktions/Konsumationsstart und -Ende
        // synchronisieren
        int totalNumOfThreads = data.getNumberOfProducers() + data.getNumberOfConsumers();
        if (!data.getNameOfInspector().equals("none")) {
            totalNumOfThreads++;
        }
        AbstractWorker.setStartBarrier(new SynchronizationBarrier(totalNumOfThreads + 1,
                new Runnable() {
                    @Override
                    public void run() {
                        // Aktivitaet #4: Ausgabe von PRODUKTION/KONSUMATION
                        // WIRD GESTARTET
                        System.out.print("\n\n\n PRODUKTION/KONSUMATION WIRD GESTARTET !!!!\n\n");
                    }
                }));

        AbstractWorker.setStopBarrier(new SynchronizationBarrier(totalNumOfThreads + 1,
                new Runnable() {
                    @Override
                    public void run() {
                        // Aktivitaet #10: Ausgabe von PRODUKTION/KONSUMATION WURDE
                        // GESTOPPT
                        System.out.print("\n\n\n PRODUKTION/KONSUMATION WURDE GESTOPPT!!!!\n");
                    }
                }));
        printer.resetQueue(totalNumOfThreads + 1);

        /* Threads erzeugen */
        ArrayList<Thread> myThreads = new ArrayList<Thread>(totalNumOfThreads);
        // Produzenten werden für Transfersummen unten weider benötigt
        ArrayList<Producer> myProducers = new ArrayList<Producer>(data.getNumberOfProducers());
        // Produzenten-Threads erzeugen und speichern
        for (int i = 1; i <= data.getNumberOfProducers(); i++) {
            Producer p = new Producer(data.getLotDefaultProduction(),
                    data.getLotFactorProduction());
            myProducers.add(p);

            Thread t = new Thread(p, data.getBaseNameOfProducers() + i);
            myThreads.add(t);
            t.setPriority(5);
            t.start();
        }

        // Konsumenten-Threads erzeugen und speichern
        for (int i = 1; i <= data.getNumberOfConsumers(); i++) {
            Consumer c = new Consumer(data.getLotDefaultConsumption(),
                    data.getLotFactorConsumption());

            Thread t = new Thread(c, data.getBaseNameOfConsumers() + i);
            myThreads.add(t);
            t.setPriority(5);
            t.start();
        }


        // Aktivitaet #2: Ausgabe der Thread-Daten des main-Thread
        System.out.print("\n Threads:");
        printer.printThreadInformation();
        AbstractWorker.getStartBarrier().queueMe();

        // queue zurücksetzen
        printer.resetQueue(totalNumOfThreads);

        Thread.sleep(data.getTimeToRun() * 1000);

        // Aktivitaet #7: Alle Thread werden interrupted
        System.out.printf("\n\n %s: Alle Threads werden nun interrupted!!\n", Thread
                .currentThread().getName());

        // Threads terminieren und synchronisieren
        for (Thread t : myThreads) {
            if (t.isAlive()) {
                t.interrupt();
            }
        }

        // Aktivitaet #8: Alle threads sind interrupted
        System.out.printf("\n\n %s: Alle Threads interrupted!!\n\n", Thread.currentThread()
                .getName());

        // Aktivitaet #10: Ausgabe von PRODUKTION/KONSUMATION WURDE GESTOPPT
        // main-Methode löst als letzter nun aus.
        AbstractWorker.getStopBarrier().queueMe();

        // Threads terminieren und synchronisieren
        for (Thread t : myThreads) {
            if (t.isAlive()) {
                t.join();
            }
        }

        // Aktivitaet #12: Ausgabe der abschliessenden Statistik
        System.out.printf("\n\n %s (Summen):", Thread.currentThread().getName());
        System.out.printf("\n Lose produziert: %d", bookkeeper.getLotsProduced());
        System.out.printf("\n Lose konsumiert: %d", bookkeeper.getLotsConsumed());
        System.out.printf("\n Produktion: %d", bookkeeper.getProductsProduced());
        System.out.printf("\n Konsumation: %d", bookkeeper.getProductsConsumed());
        System.out.printf("\n In Auslieferung an Lager (Transfer): %d", bookkeeper.getTransfer());
        System.out.printf("\n Lagerbestand: %d", store.getCurrentStock());
        System.out.printf("\n Anzahl Inspektionen: %d", 0);
        System.out.println();
        System.out.println();
    }