Created
April 3, 2014 12:37
-
-
Save iaveryanov/9953492 to your computer and use it in GitHub Desktop.
How much idling?
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package ru.inlinetelecom.vn2.util; | |
import java.util.concurrent.CountDownLatch; | |
import java.util.concurrent.ExecutorService; | |
import java.util.concurrent.Executors; | |
import java.util.concurrent.atomic.AtomicInteger; | |
import java.util.concurrent.atomic.AtomicLong; | |
/** | |
* вариант с uncontended lock (getAvailableProcessors >= worker_count | |
*/ | |
public class AtomicCasTester { | |
// счетчик холостого хода | |
private static AtomicLong idlingCounter = new AtomicLong(0); | |
/** | |
* 1) вызывается из многих потоков | |
* 2) не должно быть меньше 0 | |
* 3) если уже 0 и вызывают этот метод, то должно оставаться 0 | |
* | |
* @param counter | |
* @return 0 or value after decrement | |
*/ | |
private static int decUntilZero(AtomicInteger counter) { | |
while (true) { | |
int current = counter.get(); | |
if (current == 0) { | |
return current; | |
} | |
int next = current - 1; | |
if (counter.compareAndSet(current, next)) { | |
return next; | |
} | |
idlingCounter.incrementAndGet(); | |
} | |
} | |
public static void main(String[] args) throws InterruptedException { | |
final int initialValue = 400000000; | |
final int countOfThreads = 10; // всего потоков | |
final int countOfOperationsPerThread = initialValue/countOfThreads; // количество операций на один поток | |
final AtomicInteger counter = new AtomicInteger(initialValue); | |
ExecutorService executor = Executors.newFixedThreadPool(countOfThreads); | |
long startedAt = System.currentTimeMillis(); | |
final CountDownLatch latch = new CountDownLatch(countOfThreads); | |
for (int i = 0; i < countOfThreads; i++) { | |
executor.execute(new Runnable() { | |
@Override | |
public void run() { | |
for (int i = 0; i < countOfOperationsPerThread; i++) { | |
decUntilZero(counter); | |
} | |
latch.countDown(); | |
// System.out.println("task in progress..." + (latch.getCount())); | |
} | |
}); | |
} | |
System.out.println("всех ждёмс, однако..."); | |
latch.await(); | |
long elapsed = System.currentTimeMillis() - startedAt; | |
executor.shutdown(); // за ненадобностью более! | |
System.out.println("Ну наконец-ТА дождалИСА!!! Урра товариСЧи, уРРа!"); | |
printReport(initialValue, countOfThreads, countOfOperationsPerThread, counter, elapsed); | |
} | |
private static void printReport(int initialValue, int countOfThreads, int countOfOperationsPerThread, AtomicInteger counter, long elapsed) { | |
System.out.printf("================================================%n"); | |
int current = counter.get(); | |
int operations = initialValue - current; | |
System.out.printf("== INPUT DATA %n"); | |
line("initial val", initialValue); | |
line("threads", countOfThreads); | |
line("operations/threads", countOfOperationsPerThread); | |
System.out.printf("== RESULTS %n"); | |
lineWithPercent("current val", current, percent(current, initialValue)); | |
lineWithPercent("operations", operations, percent(operations, initialValue)); | |
lineWithPercent("idling", idlingCounter.get(), percent(idlingCounter.get(), initialValue)); | |
line("elapsed(millis)", elapsed); | |
} | |
private static void line(String key, long value) { | |
System.out.printf("%-20s: %-10d %n", key, value); | |
} | |
private static void lineWithPercent(String key, long value, double percent) { | |
System.out.printf("%-20s: %-10d %.2f%% %n", key, value, percent); | |
} | |
private static float percent(float part, float total) { | |
return (part / total * 100); | |
} | |
private static float percent(long part, long total) { | |
return percent((float) part, (float) total); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment