public void start()
    {
        if (this.isRunning || this.simulationResult != null) {
            return;
        }
        
        this.latch = new CountDownLatch(this.nrOfWorkers);
        int roundsPerWorker = getNrOfRoundsPerWorker(this.nrOfWorkers);
        
        this.executor = Executors.newFixedThreadPool(this.nrOfWorkers);
    
        int workerUpdateInterval = getUpdateInterval(this.nrOfWorkers);
        
        for (int i = 0; i < this.nrOfWorkers; i++) {
            SimulationWorker worker;
            WorkerBuilder builder;
            if (this.gameType == PokerType.TEXAS_HOLDEM) {
                builder = TexasHoldemWorker.builder();
            } else if (this.gameType == PokerType.OMAHA) {
                builder = OmahaWorker.builder();
            } else if (this.gameType == PokerType.OMAHA_HILO) {
                builder = OmahaHiLoWorker.builder();
            } else if (this.gameType == PokerType.FOMAHA) {
                builder = FiveCardOmahaWorker.builder();
            } else {
                builder = FiveCardOmahaHiLoWorker.builder();
            }
            
            builder.setCommunityCards(this.communityCards)
                .setNotifier(this)
                .setRounds(roundsPerWorker)
                .setUpdateInterval(workerUpdateInterval);
            
            for (PlayerProfile profile : this.profiles) {
                builder.addPlayer(profile);
            }
            
            worker = builder.build();
            
            this.executor.execute(worker);
            this.workers.add(worker);
        }
        
        this.startTime = System.currentTimeMillis();
        
        this.isRunning = true;
        
        Thread masterThread = new Thread(new Supervisor());
        masterThread.setDaemon(true);
        masterThread.start();
        
        SimulationEvent event = new SimulationEvent(SimulationEvent.EVENT_SIM_STARTED, this.nrOfWorkers);
        this.notifiable.onSimulationStart(event);
    }