To illustrate the advantage of a pinned thread, we code a program that launches a bunch of threads to do a simple task and pin one of them to a processor. At the end you can see that the pinned thread is much ahead of the other threads. That’s because the other threads have to compete for the available processors while the pinned thread has a whole processor for itself. Without context switches and interruptions the pinned thread can perform its job much faster than the other ones.
import com.coralblocks.coralthreads.Affinity; import com.coralblocks.coralbits.util.SystemUtils; public class ManyThreads { public static void main(String[] args) throws Exception { final int nThreads = SystemUtils.getInt("nThreads", 20); final int threadToBind = SystemUtils.getInt("threadToBind", 10); final int procToBind = SystemUtils.getInt("procToBind", 2); final long maxLong = SystemUtils.getLong("maxLong", 1000000000L); class PinnedThread extends Thread { long overlaps = 0; long count = 0; volatile boolean running = true; PinnedThread(String name) { super(name); } void stopMe() { running = false; } @Override public void run() { Affinity.bind(); try { while(running) { if (count++ == maxLong) { overlaps++; count = 0; } } } finally { Affinity.unbind(); } } } final PinnedThread[] threads = new PinnedThread[nThreads]; for(int i = 0; i < threads.length; i++) { threads[i] = new PinnedThread(i == threadToBind ? "PinnedThread" : "Thread" + i); } if (procToBind >= 0) Affinity.assignToProcessor(procToBind, threads[threadToBind]); for(PinnedThread t : threads) t.start(); System.out.println(); Affinity.printSituation(); Runtime.getRuntime().addShutdownHook(new Thread() { @Override public void run() { for(PinnedThread t : threads) t.stopMe(); for(PinnedThread t : threads) try { t.join(); } catch(Exception e) { } System.out.println(); for(PinnedThread t : threads) { System.out.println(t.getName() + ": overlaps=" + t.overlaps + " count=" + t.count); } } }); } }
The output:
$ java -cp coralthreads-all.jar com.coralblocks.coralthreads.sample.ManyThreads CpuInfo: [nChips=1, nCoresPerChip=4, hyper-threading=true, nProcessors=8, procIds=0,1,2,3,4,5,6,7] Chip-0: Core-0: Processor-0: free Processor-4: free Core-1: Processor-1: free Processor-5: free Core-2: Processor-2: bound to PinnedThread (running pid=3406) Processor-6: free Core-3: Processor-3: free Processor-7: free ^C Thread0: overlaps=18 count=219401874 Thread1: overlaps=19 count=261705318 Thread2: overlaps=18 count=610599006 Thread3: overlaps=18 count=134022214 Thread4: overlaps=18 count=706525436 Thread5: overlaps=18 count=53884487 Thread6: overlaps=17 count=614235810 Thread7: overlaps=18 count=288563757 Thread8: overlaps=18 count=437900710 Thread9: overlaps=18 count=913959165 PinnedThread: overlaps=87 count=402690338 Thread11: overlaps=17 count=965738516 Thread12: overlaps=18 count=847900384 Thread13: overlaps=19 count=6207215 Thread14: overlaps=19 count=19490349 Thread15: overlaps=18 count=60562201 Thread16: overlaps=17 count=940538865 Thread17: overlaps=18 count=730871356 Thread18: overlaps=18 count=187664691 Thread19: overlaps=17 count=719411214