package ar.com.javacuriosities.concurrency.management;
import java.lang.management.*;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicLong;
public class MultiCoreTesting {
private static final int NUMBER_OF_THREADS = 16;
// Creamos un CountDown de un solo thread
private static CountDownLatch countDownLatch = new CountDownLatch(NUMBER_OF_THREADS);
// Definimos una operación atómica para evitar perder valores por distintos threads
private static AtomicLong total = new AtomicLong();
public static void main(String[] args) throws InterruptedException {
// Preguntamos la cantidad de procesadores disponibles
System.out.println("Available Processors: " + Runtime.getRuntime().availableProcessors());
// Calculamos el "wall clock time" en nano segundos
long elapsedTime = System.nanoTime();
// Creamos y empezamos a ejecutar tantos hilos como diga nuestra constante
for (int i = 0; i < NUMBER_OF_THREADS; i++) {
Thread thread = new Thread(new Task());
thread.start();
}
// Esperamos todos los hilos
countDownLatch.await();
// Calculamos el tiempo, desde el punto de vista del usuario
elapsedTime = System.nanoTime() - elapsedTime;
/*
* Informamos los dos tiempos
* Elapsed time: Tiempo de vista por el usuario
* CPU Time: Tiempo consumido por el procesador
*/
System.out.println("Total elapsed time " + elapsedTime);
System.out.println("Total thread CPU time " + total.get());
// Calculamos el factor (Total CPU Time / Elapsed Time)
double factor = total.get();
factor /= elapsedTime;
// Imprimimos el factor
System.out.printf("Factor: %.2f%n", factor);
/*
* El factor debe ser un numero igual o cercano al numero de procesadores disponibles
*
* Runtime.getRuntime().availableProcessors() para indicarnos que varios
* Threads están corriendo de forma concurrente.
*
* Ejemplo:
* Si Tenemos 4 procesadores y corremos 4 hilos el factor deberla ser cercano a 4
* Si Tenemos 4 procesadores y corremos 8 hilos el factor va a ser un numero cercano a 4
* porque solo podemos ejecutar 4 hilos de forma concurrente
* Si Tenemos 4 procesadores y corremos 2 hilos el factor va a ser un numero cercano a 2
*/
}
private static long measureThreadCpuTime() {
// Pedimos el ThreadMXBean
ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();
// Pedimos el cpuTime inicial para el hilo actual
long cpuTime = threadMXBean.getCurrentThreadCpuTime();
/* Creamos una variable la cual vamos a ir modificando en el ciclo
* este código esta puesto porque si ponemos un ciclo vació el compilador
* se da cuenta de esto y lo remueve para incrementar la performance
*/
long total = 0;
for (int i = 0; i < 1000 * 1000 * 1000; i++) {
total += i;
total *= 10;
}
// Calculamos la diferencia entre el tiempo final y el inicial
cpuTime = threadMXBean.getCurrentThreadCpuTime() - cpuTime;
/*
* Imprimimos el valor del total para mostrar que siempre es igual, además
* mostramos el CPU Time y devolvemos el cpu time consumido para después hacer
* la cuenta del factor
*/
System.out.println("Total: " + total + " - " + Thread.currentThread() + ": cpuTime = " + cpuTime);
return cpuTime;
}
private static final class Task implements Runnable {
@Override
public void run() {
total.addAndGet(measureThreadCpuTime());
countDownLatch.countDown();
}
}
}