Modified FlowSynchronizer#synchronize to return Future object so that caller can know when synchronization finished.
diff --git a/src/main/java/net/onrc/onos/ofcontroller/flowprogrammer/FlowSynchronizer.java b/src/main/java/net/onrc/onos/ofcontroller/flowprogrammer/FlowSynchronizer.java
index 7d5527b..415b1b1 100644
--- a/src/main/java/net/onrc/onos/ofcontroller/flowprogrammer/FlowSynchronizer.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/flowprogrammer/FlowSynchronizer.java
@@ -7,8 +7,10 @@
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.concurrent.Callable;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.Future;
+import java.util.concurrent.FutureTask;
 
 import org.openflow.protocol.OFFlowMod;
 import org.openflow.protocol.OFMatch;
@@ -44,26 +46,27 @@
 
     private GraphDBOperation dbHandler;
     protected IFlowPusherService pusher;
-    private Map<IOFSwitch, Thread> switchThreads; 
+    private Map<IOFSwitch, FutureTask<SyncResult>> switchThreads; 
 
     public FlowSynchronizer() {
 	dbHandler = new GraphDBOperation("");
-	switchThreads = new HashMap<IOFSwitch, Thread>();
+	switchThreads = new HashMap<IOFSwitch, FutureTask<SyncResult>>();
     }
 
     @Override
-    public void synchronize(IOFSwitch sw) {
+    public Future<SyncResult> synchronize(IOFSwitch sw) {
 	Synchronizer sync = new Synchronizer(sw);
-	Thread t = new Thread(sync);
-	switchThreads.put(sw, t);
-	t.start();
+	FutureTask<SyncResult> task = new FutureTask<SyncResult>(sync);
+	switchThreads.put(sw, task);
+	task.run();
+	return task;
     }
     
     @Override
     public void interrupt(IOFSwitch sw) {
-	Thread t = switchThreads.remove(sw);
+	FutureTask<SyncResult> t = switchThreads.remove(sw);
 	if(t != null) {
-	    t.interrupt();
+		t.cancel(true);
 	}	
     }
 
@@ -80,7 +83,7 @@
      * @author Brian
      *
      */
-	protected class Synchronizer implements Runnable {
+	protected class Synchronizer implements Callable<SyncResult> {
 	IOFSwitch sw;
 	ISwitchObject swObj;
 
@@ -91,13 +94,15 @@
 	}
 
 	@Override
-	public void run() {
+	public SyncResult call() {
 	    // TODO: stop adding other flow entries while synchronizing
 	    //pusher.suspend(sw);
 	    Set<FlowEntryWrapper> graphEntries = getFlowEntriesFromGraph();
 	    Set<FlowEntryWrapper> switchEntries = getFlowEntriesFromSwitch();
-	    compare(graphEntries, switchEntries);
+	    SyncResult result = compare(graphEntries, switchEntries);
 	    //pusher.resume(sw);
+	    
+	    return result;
 	}
 
 	/**
@@ -107,7 +112,7 @@
 	 * @param graphEntries Flow entries in GraphDB.
 	 * @param switchEntries Flow entries in switch.
 	 */
-	private void compare(Set<FlowEntryWrapper> graphEntries, Set<FlowEntryWrapper> switchEntries) {
+	private SyncResult compare(Set<FlowEntryWrapper> graphEntries, Set<FlowEntryWrapper> switchEntries) {
 	    int added = 0, removed = 0, skipped = 0;
 	    for(FlowEntryWrapper entry : switchEntries) {
 		if(graphEntries.contains(entry)) {
@@ -128,6 +133,8 @@
 	    log.debug("Flow entries added "+ added + ", " +
 		      "Flow entries removed "+ removed + ", " +
 		      "Flow entries skipped " + skipped);
+	    
+	    return new SyncResult(added, removed, skipped);
 	}
 
 	/**
diff --git a/src/main/java/net/onrc/onos/ofcontroller/flowprogrammer/IFlowSyncService.java b/src/main/java/net/onrc/onos/ofcontroller/flowprogrammer/IFlowSyncService.java
index 4e6efaf..4fe0857 100644
--- a/src/main/java/net/onrc/onos/ofcontroller/flowprogrammer/IFlowSyncService.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/flowprogrammer/IFlowSyncService.java
@@ -1,7 +1,8 @@
 package net.onrc.onos.ofcontroller.flowprogrammer;
 
+import java.util.concurrent.Future;
+
 import net.floodlightcontroller.core.IOFSwitch;
-import net.floodlightcontroller.core.IOFSwitchListener;
 import net.floodlightcontroller.core.module.IFloodlightService;
 
 /**
@@ -11,7 +12,19 @@
  *
  */
 public interface IFlowSyncService extends IFloodlightService {
-    public void synchronize(IOFSwitch sw);
+    public Future<SyncResult> synchronize(IOFSwitch sw);
     
     public void interrupt(IOFSwitch sw);
+    
+    public class SyncResult {
+    	public final int flowAdded;
+    	public final int flowRemoved;
+    	public final int flowSkipped;
+    	
+    	public SyncResult(int added, int removed, int skipped) {
+    		flowAdded = added;
+    		flowRemoved = removed;
+    		flowSkipped = skipped;
+    	}
+    }
 }
diff --git a/src/test/java/net/onrc/onos/ofcontroller/flowprogrammer/FlowSynchronizerTest.java b/src/test/java/net/onrc/onos/ofcontroller/flowprogrammer/FlowSynchronizerTest.java
index 5aac239..68b4f1f 100644
--- a/src/test/java/net/onrc/onos/ofcontroller/flowprogrammer/FlowSynchronizerTest.java
+++ b/src/test/java/net/onrc/onos/ofcontroller/flowprogrammer/FlowSynchronizerTest.java
@@ -6,13 +6,14 @@
 import java.util.ArrayList;
 import java.util.List;
 import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
 
-import io.netty.util.concurrent.Future;
 import net.floodlightcontroller.core.IOFSwitch;
 import net.onrc.onos.graph.GraphDBOperation;
 import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IFlowEntry;
 import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.ISwitchObject;
 import net.onrc.onos.ofcontroller.flowmanager.FlowDatabaseOperation;
+import net.onrc.onos.ofcontroller.flowprogrammer.IFlowSyncService.SyncResult;
 import net.onrc.onos.ofcontroller.util.FlowEntry;
 import net.onrc.onos.ofcontroller.util.FlowEntryId;
 
@@ -91,7 +92,7 @@
 		initMockGraph(new long[] {1});
 		
 		// synchronize
-		doSynchronization(sw,1000);
+		doSynchronization(sw);
 		
 		// check if flow is not changed
 		assertEquals(0, idAdded.size());
@@ -110,7 +111,7 @@
 		initMockGraph(new long[] {1});
 		
 		// synchronize
-		doSynchronization(sw,1000);
+		doSynchronization(sw);
 		
 		// check if single flow is installed
 		assertEquals(1, idAdded.size());
@@ -130,7 +131,7 @@
 		initMockGraph(new long[] {});
 		
 		// synchronize
-		doSynchronization(sw,1000);
+		doSynchronization(sw);
 		
 		// check if single flow is deleted
 		assertEquals(0, idAdded.size());
@@ -151,7 +152,7 @@
 		initMockGraph(new long[] {2,3,4,5});
 		
 		// synchronize
-		doSynchronization(sw,1000);
+		doSynchronization(sw);
 		
 		// check if two flows {4,5} is installed and one flow {1} is deleted
 		assertEquals(2, idAdded.size());
@@ -179,7 +180,7 @@
 		initMockGraph(dbIdList);
 
 		// synchronize
-		doSynchronization(sw, 3000);
+		doSynchronization(sw);
 		
 		// check if 1500 flows {2000-3499} is installed and 1500 flows {0,...,1499} is deleted
 		assertEquals(1500, idAdded.size());
@@ -299,15 +300,14 @@
 	 * Instantiate FlowSynchronizer and sync flows.
 	 * @param sw Target IOFSwitch object
 	 */
-	private void doSynchronization(IOFSwitch sw, long wait) {
+	private void doSynchronization(IOFSwitch sw) {
 		sync = new FlowSynchronizer();
 		sync.init(pusher);
-		sync.synchronize(sw);
-		
+		Future<SyncResult> future = sync.synchronize(sw);
 		try {
-			Thread.sleep(wait);
-		} catch (InterruptedException e) {
-			fail("Failed to sleep");
+			future.get();
+		} catch (Exception e) {
+			fail("Failed to Future#get()");
 		}
 	}
 }