package shootout.threadring; /** * The Computer Language Benchmarks Game * http://shootout.alioth.debian.org/ * * contributed by Fabien Le Floc'h * * Java implementation of thread-ring benchmark. Best performance is achieved with * MAX_THREAD=1 as the thread-ring test is bested with only 1 os thread. * This implementation shows using a simple thread pool solves the thread context * switch issue. */ import java.util.concurrent.*; public class ThreadRing { private static final int MAX_NODES = 503; private static final int MAX_THREADS = 503; private ExecutorService executor; private final int N; static final CountDownLatch cdl = new CountDownLatch(1); public static void main(String[] args) throws InterruptedException { long start = System.currentTimeMillis(); int n = 500; try { n = Integer.parseInt(args[0]); } catch (Exception e) {} ThreadRing ring = new ThreadRing(n); Node node = ring.start(MAX_NODES); node.sendMessage(new TokenMessage(1,0)); cdl.await(); long total = System.currentTimeMillis() - start; System.out.println("[ThreadRing-Java Benchmark Result: " + total + "]"); } public ThreadRing(int n) { N = n; } public Node start(int n) { Node[] nodes = spawnNodes(n); connectNodes(n, nodes); return nodes[0]; } private Node[] spawnNodes(int n) { executor = Executors.newFixedThreadPool(MAX_THREADS); Node[] nodes = new Node[n+1]; for (int i = 0; i < n ; i++) { nodes[i] = new Node(i+1, null); } return nodes; } public void connectNodes(int n, Node[] nodes) { nodes[n] = nodes[0]; for (int i=0; i<n; i++) { nodes[i].connect(nodes[i+1]); } } private static class TokenMessage { private int nodeId; private volatile int value; private boolean isStop; public TokenMessage(int nodeId, int value) { this.nodeId = nodeId; this.value = value; } public TokenMessage(int nodeId, int value, boolean isStop) { this.nodeId = nodeId; this.value = value; this.isStop = isStop; } } private class Node implements Runnable { private int nodeId; private Node nextNode; private BlockingQueue<TokenMessage> queue = new LinkedBlockingQueue<TokenMessage>(); private boolean isActive = false; private int counter; public Node(int id, Node nextNode) { this.nodeId = id; this.nextNode = nextNode; this.counter = 0; } public void connect(Node node) { this.nextNode = node; isActive = true; } public void sendMessage(TokenMessage m) { queue.add(m); executor.execute(this); } public void run() { if (isActive) { try { TokenMessage m = queue.take(); if (m.isStop) { int nextValue = m.value+1; if (nextValue == MAX_NODES) { // System.out.println("last one"); executor.shutdown(); cdl.countDown(); } else { m.value = nextValue; nextNode.sendMessage(m); } isActive = false; // System.out.println("ending node "+nodeId); } else { if (m.value == N) { System.out.println(nodeId); nextNode.sendMessage(new TokenMessage(nodeId, 0, true)); } else { m.value = m.value + 1; nextNode.sendMessage(m); } } } catch (InterruptedException ie) { ie.printStackTrace(); } } } } }