private synchronized void runSynced() {
        // WAIT UNTIL SEM_PAUSE IS 0 - THAT IS, THERE ARE NO PAUSE REQUESTS ON THIS THREAD
        while (sem_pause > 0) {
            try {
                wait();
            } catch (InterruptedException ex) {

            }
        }

        // GET THE START TIME
        long startTime = System.nanoTime();

        // PASS ON THE METHOD TO THE CHILD WHILE OBSERVING STATISTICS
        child.run();

        // GET THE DELTA TIME AND FIND THE WAIT TIME
        long stopTime = System.nanoTime();
        long delta = targetNanos - (stopTime - startTime); // TOTAL IN NANOSECONDS, SUBTRACT 500000 FOR ROUNDING 

        // SLEEP FOR SOME AMOUNT OF TIME IF NEEDED
        if (delta > 0 && !unlockedFramerate) {
            try {
                // Thread.sleep((delta + 500000) / 1000000);
                Thread.sleep(delta / 1000000);

                // THIS PART IS CPU HEAVY BUT RELATIVELY SHORT COMPARED TO THE LONGER SLEEP
                if (waitNanos) {
                    long endTime = targetNanos + startTime;
                    while (System.nanoTime() < endTime) {
                        Thread.yield();
                    }
                }
                // JUST DO A SIMPLE LOOP FOR THE NANOSECONDS
            } catch (InterruptedException ex) {
            }
        }

        // CALCULATE STATISTICS AND FINISH UP
        long runtime = System.nanoTime() - startTime;

        averageRuntime = (15 * lastRuntime + runtime) / 16;
        performance = (float) runtime / targetNanos;
        lastRuntime = runtime;
        framenumber++;
    }