Estoy probando HashIds para colisiones. Aquí está la dependencia:

    <!-- https://mvnrepository.com/artifact/org.hashids/hashids -->
    <dependency>
        <groupId>org.hashids</groupId>
        <artifactId>hashids</artifactId>
        <version>1.0.3</version>
    </dependency>

Estoy usando el siguiente código:

    Hashids hashids = new Hashids("xyz", 6, "0123456789ABCDEFGHJKLMNPQRSTUVWXYZ");

    System.out.println("*******************************************************************");
    System.out.println("Started");

    Set<String> set = new HashSet();

    ExecutorService executor = Executors.newFixedThreadPool(4);

    AtomicLong count = new AtomicLong(0);
    final long max = 10_000_000;
    for (long i = 1; i <= max; i++) {

        executor.execute(() -> {
            set.add(hashids.encode(count.incrementAndGet()));

            // This is just to show me that there is some activity going on
            if (count.get() % 100_000 == 0) {
                System.out.println(count.get() + ": " + new Date());
            }
        });
    }

    // Wait till the executor service tasks are done 
    executor.shutdown();
    while (!executor.isTerminated()) {
        Thread.sleep(1000);
    }

    // Assert that the Set did not receive duplicates
    Assert.assertEquals(max, set.size());

    System.out.println("Ended");
    System.out.println("*******************************************************************");

Entonces, puse un ExecutorService para hacerlo un poco más rápido pero tengo problemas. Ya sea

  1. ExecutorService no se completa y se cuelga allí
  2. Set contiene valores duplicados, por lo tanto, la aserción falla
  3. Usar el ciclo simple for es mucho más rápido que cuando se usa ExecutorService

¿Qué podría estar mal con este código?

2
Kihats 24 jun. 2020 a las 08:22

2 respuestas

La mejor respuesta
  1. Necesita llamar a executeor.awaitTermination justo después de executor.shutdown() ;
  2. Su Set no es seguro para subprocesos, intente envolver su conjunto con Collections.synchronizedSet(set) o cree un conjunto basado en ConcurrentHashMap.newKeySet(), vea esta discusión sobre conjunto de subprocesos seguros.
3
Dai 24 jun. 2020 a las 05:52

Poner en cola muchas tareas relativamente rápidas puede ser una gran carga. En su lugar, solo puede poner en cola 4 tareas, que se repiten en una partición de los números enteros. Esto será mucho más rápido debido a la sobrecarga reducida de las colas y posiblemente a la localidad del código (cachés). Además, evita el acceso concurrente a contadores y colecciones.

0
eckes 24 jun. 2020 a las 06:22