@@ -0,0 +1,2796 @@
+package org.jgroups.util;%0A%0Aimport java.util.Set;%0Aimport java.util.HashSet;%0Aimport java.util.concurrent.locks.Lock;%0Aimport java.util.concurrent.locks.ReentrantLock;%0Aimport java.util.concurrent.locks.Condition;%0A%0A/**%0A * @author Bela Ban%0A * @version $Id: Metronome.java,v 1.1 2009/06/22 16:15:21 belaban Exp $%0A */%0Apublic class Metronome implements Runnable %7B%0A    private final Set%3CThread%3E threads=new HashSet%3CThread%3E();%0A    private int tick=0;%0A    private volatile Thread worker=null;%0A    private int interval=10;%0A    private final Lock lock=new ReentrantLock();%0A    private final Condition cond=lock.newCondition();%0A%0A%0A    public Metronome(int interval) %7B%0A        this.interval=interval;%0A    %7D%0A%0A    public void add(final Thread thread) %7B%0A        synchronized(threads) %7B%0A            threads.add(thread);%0A            if(worker == null %7C%7C !worker.isAlive()) %7B%0A                worker=new Thread(this, %22MetronomeThread%22);%0A                worker.setDaemon(true);%0A                worker.start();%0A            %7D%0A        %7D%0A    %7D%0A%0A    public void remove(final Thread thread) %7B%0A        synchronized(threads) %7B%0A            threads.remove(thread);%0A        %7D%0A    %7D%0A%0A    public void waitFor(int tick) %7B%0A        add(Thread.currentThread());%0A        while(true) %7B%0A            lock.lock();%0A            try %7B%0A                if(tick %3E this.tick) %7B%0A                    try %7B%0A                        cond.await();%0A                    %7D%0A                    catch(InterruptedException e) %7B%0A                        Thread.currentThread().interrupt();%0A                    %7D%0A                %7D%0A                else%0A                    return;%0A            %7D%0A            finally %7B%0A                lock.unlock();%0A            %7D%0A        %7D%0A    %7D%0A%0A    public void stop() %7B%0A        worker=null;%0A        synchronized(threads) %7B%0A            threads.clear();%0A        %7D%0A    %7D%0A%0A%0A    public void run() %7B%0A        while(worker != null && Thread.currentThread().equals(worker)) %7B%0A            boolean all_blocked=true;%0A            synchronized(threads) %7B%0A                if(threads.isEmpty())%0A                    break;%0A%0A                for(Thread tmp: threads) %7B%0A                    Thread.State state=tmp.getState();%0A                    if(state != Thread.State.WAITING && state != Thread.State.BLOCKED) %7B%0A                        all_blocked=false;%0A                        System.out.println(%22state of %22 + tmp + %22: %22 + state);%0A                        break;%0A                    %7D%0A                %7D%0A            %7D%0A            if(all_blocked) %7B%0A                lock.lock();%0A                try %7B%0A                    tick++;%0A                    cond.signalAll();%0A                %7D%0A                finally %7B%0A                    lock.unlock();%0A                %7D%0A            %7D%0A%0A            Util.sleep(interval);%0A        %7D%0A        worker=null;%0A    %7D%0A%7D%0A

possible equivalent to MTC