public static void main(String[] args) throws BadStateMachineSpecification, InvalidEventException, InterruptedException {
     
       ConcurrentStateMachine<PerformanceEnum>[] concurrentFSM = new ConcurrentStateMachine[FSMS];
       CountDownLatch latch = new CountDownLatch(FSMS);
       TestThread[] testThreads = new TestThread[FSMS];
       for( int i = 0 ; i < FSMS; ++i) {
        StateMachine<PerformanceEnum> fsm
                = new StateMachineBuilder<PerformanceEnum>(StateMachineBuilder.FSM_TYPES.BASIC, PerformanceEnum.class).
                addState(STATE_INITIAL, new EmptyState()).markStateAsInitial().addDefaultTransition(STATE_START).
                addState(STATE_START, new MarkState(STATE_START)).addTransition(PerformanceEnum.A, STATE_MIDDLE).
                addState(STATE_MIDDLE, new EmptyState()).addTransition(PerformanceEnum.A, STATE_MIDDLE).
                addTransition(PerformanceEnum.B, STATE_FINISH).
                addState(STATE_FINISH, new MarkState(STATE_FINISH)).addDefaultTransition(STATE_INITIAL).build();
        concurrentFSM[i] = new ConcurrentStateMachine<>(fsm, QUEUE_SIZE);
        concurrentFSM[i].completeInitialization();
       }
       for(int i = 0 ; i< FSMS; ++i){
           testThreads[i] = new TestThread(TRANSACTIONS_PER_FSM/QUEUE_SIZE/CLIENTS_PER_FSM , 
                   QUEUE_SIZE, CLIENTS_PER_FSM, concurrentFSM[i], latch);
           testThreads[i].start();
       }
       for(int i = 0 ; i< FSMS; ++i)
           testThreads[i].join();
       long maxDelta =0;
       for(int i = 0 ; i < FSMS; ++i) {
           long start = (Long) concurrentFSM[i].getProperty(STATE_START);
           long finish = (Long) concurrentFSM[i].getProperty(STATE_FINISH);
           if ( maxDelta < (finish - start))
               maxDelta  = (finish - start);
       }
       
       System.out.println(" FSMs="+FSMS+" senders =" +FSMS*CLIENTS_PER_FSM+" blockSize="+QUEUE_SIZE);
       
       System.out.println(" Total transitions="+TRANSACTIONS_PER_FSM *FSMS + " elapsed miliseconds="+maxDelta
       + " average throughput TP/miliSec "+ ((long)TRANSACTIONS_PER_FSM)*FSMS/maxDelta);
    
    
    int[] FSMS_SET= {2,5,10,20};
    int[] CLIENTS_SET = {2,5,10};
    int[] TRANSICTIONS_PER_FSM_SET= {10000000,100000000/*,1000000000*/};
   
    for(int fsms:FSMS_SET)
        for(int clients: CLIENTS_SET)
            for(int transitions: TRANSICTIONS_PER_FSM_SET){
                runTest(fsms, clients, transitions);
            }
    }