public void runThreads() {
        ExecutorService es = Executors.newFixedThreadPool(10);
        List<Future<?>> futures = new ArrayList<>(NUM_THREADS);

        System.out.println("Amount before: " + bank.getTotalAmount());

        for (int i = 0; i < NUM_THREADS; ++i) {
            Runnable task;
            task = new Runnable() {
                private final Account[] transferAccounts = getRandomPair();

                @Override
                public void run() {
                    bank.transfer(transferAccounts[0], transferAccounts[1],
                            (int) (Math.random() * MAX_TRANSFER));

                    numTransactions.incrementAndGet();
                }

            };

            futures.add(es.submit(task));
        }

        // wait for result
        for (int i = 0; i < NUM_THREADS; ++i) {
            try {
                futures.get(i).get();
            } catch (InterruptedException e) {
                System.out.println("Transfer interrupted");
                es.shutdown();
                return;
            } catch (ExecutionException e) {
                System.out.println("Transfer execution interrupted");
                es.shutdown();
                return;
            }
        }

        System.out.println("Amount after: " + bank.calcTotalAmount());
        System.out.println("Number of transactions: " + numTransactions);
        System.out.println("Number of threads " + NUM_THREADS);
        es.shutdown();
    }