diff --git a/api/net/sf/briar/api/transport/BatchConnectionFactory.java b/api/net/sf/briar/api/transport/BatchConnectionFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..547dc83a741d468bfd191ecbe0b05828e0a11f7b
--- /dev/null
+++ b/api/net/sf/briar/api/transport/BatchConnectionFactory.java
@@ -0,0 +1,13 @@
+package net.sf.briar.api.transport;
+
+import net.sf.briar.api.ContactId;
+import net.sf.briar.api.TransportId;
+
+public interface BatchConnectionFactory {
+
+	void createIncomingConnection(ContactId c, BatchTransportReader r,
+			byte[] encryptedIv);
+
+	void createOutgoingConnection(TransportId t, ContactId c,
+			BatchTransportWriter w);
+}
diff --git a/api/net/sf/briar/api/transport/StreamConnectionFactory.java b/api/net/sf/briar/api/transport/StreamConnectionFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..933b9bb9c6692f0fadf0547e78839fdefd9b34d5
--- /dev/null
+++ b/api/net/sf/briar/api/transport/StreamConnectionFactory.java
@@ -0,0 +1,13 @@
+package net.sf.briar.api.transport;
+
+import net.sf.briar.api.ContactId;
+import net.sf.briar.api.TransportId;
+
+public interface StreamConnectionFactory {
+
+	void createIncomingConnection(ContactId c, StreamTransportConnection s,
+			byte[] encryptedIv);
+
+	void createOutgoingConnection(TransportId t, ContactId c,
+			StreamTransportConnection s);
+}
diff --git a/api/net/sf/briar/api/transport/batch/BatchConnectionFactory.java b/api/net/sf/briar/api/transport/batch/BatchConnectionFactory.java
deleted file mode 100644
index 590ffc25dea0ac971f705c7c7a86626c99461c1d..0000000000000000000000000000000000000000
--- a/api/net/sf/briar/api/transport/batch/BatchConnectionFactory.java
+++ /dev/null
@@ -1,15 +0,0 @@
-package net.sf.briar.api.transport.batch;
-
-import net.sf.briar.api.ContactId;
-import net.sf.briar.api.TransportId;
-import net.sf.briar.api.transport.BatchTransportReader;
-import net.sf.briar.api.transport.BatchTransportWriter;
-
-public interface BatchConnectionFactory {
-
-	Runnable createIncomingConnection(ContactId c, BatchTransportReader r,
-			byte[] encryptedIv);
-
-	Runnable createOutgoingConnection(TransportId t, ContactId c,
-			BatchTransportWriter w);
-}
diff --git a/api/net/sf/briar/api/transport/stream/StreamConnectionFactory.java b/api/net/sf/briar/api/transport/stream/StreamConnectionFactory.java
deleted file mode 100644
index e255c4acc0de2955a9afe3cecae463ec84c5d311..0000000000000000000000000000000000000000
--- a/api/net/sf/briar/api/transport/stream/StreamConnectionFactory.java
+++ /dev/null
@@ -1,14 +0,0 @@
-package net.sf.briar.api.transport.stream;
-
-import net.sf.briar.api.ContactId;
-import net.sf.briar.api.TransportId;
-import net.sf.briar.api.transport.StreamTransportConnection;
-
-public interface StreamConnectionFactory {
-
-	Runnable[] createIncomingConnection(ContactId c,
-			StreamTransportConnection s, byte[] encryptedIv);
-
-	Runnable[] createOutgoingConnection(TransportId t, ContactId c,
-			StreamTransportConnection s);
-}
diff --git a/components/net/sf/briar/transport/ConnectionDispatcherImpl.java b/components/net/sf/briar/transport/ConnectionDispatcherImpl.java
index 1f1185bb9c8cc6d451b570408de6b57063f91b85..97a815a1ca4f442f1c3d380ead14fd70340b680c 100644
--- a/components/net/sf/briar/transport/ConnectionDispatcherImpl.java
+++ b/components/net/sf/briar/transport/ConnectionDispatcherImpl.java
@@ -4,39 +4,35 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.util.HashMap;
 import java.util.Map;
-import java.util.concurrent.Executor;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
 import net.sf.briar.api.ContactId;
 import net.sf.briar.api.TransportId;
 import net.sf.briar.api.db.DbException;
+import net.sf.briar.api.transport.BatchConnectionFactory;
 import net.sf.briar.api.transport.BatchTransportReader;
 import net.sf.briar.api.transport.BatchTransportWriter;
 import net.sf.briar.api.transport.ConnectionDispatcher;
 import net.sf.briar.api.transport.ConnectionRecogniser;
 import net.sf.briar.api.transport.ConnectionRecogniserFactory;
+import net.sf.briar.api.transport.StreamConnectionFactory;
 import net.sf.briar.api.transport.StreamTransportConnection;
 import net.sf.briar.api.transport.TransportConstants;
-import net.sf.briar.api.transport.batch.BatchConnectionFactory;
-import net.sf.briar.api.transport.stream.StreamConnectionFactory;
 
 public class ConnectionDispatcherImpl implements ConnectionDispatcher {
 
 	private static final Logger LOG =
 		Logger.getLogger(ConnectionDispatcherImpl.class.getName());
 
-	private final Executor executor;
 	private final ConnectionRecogniserFactory recFactory;
 	private final BatchConnectionFactory batchConnFactory;
 	private final StreamConnectionFactory streamConnFactory;
 	private final Map<TransportId, ConnectionRecogniser> recognisers;
 
-	ConnectionDispatcherImpl(Executor executor,
-			ConnectionRecogniserFactory recFactory,
+	ConnectionDispatcherImpl(ConnectionRecogniserFactory recFactory,
 			BatchConnectionFactory batchConnFactory,
 			StreamConnectionFactory streamConnFactory) {
-		this.executor = executor;
 		this.recFactory = recFactory;
 		this.batchConnFactory = batchConnFactory;
 		this.streamConnFactory = streamConnFactory;
@@ -67,9 +63,7 @@ public class ConnectionDispatcherImpl implements ConnectionDispatcher {
 			r.dispose(false);
 			return;
 		}
-		// Pass the connection to the executor and return
-		executor.execute(batchConnFactory.createIncomingConnection(c, r,
-				encryptedIv));
+		batchConnFactory.createIncomingConnection(c, r, encryptedIv);
 	}
 
 	private byte[] readIv(InputStream in) throws IOException {
@@ -96,7 +90,7 @@ public class ConnectionDispatcherImpl implements ConnectionDispatcher {
 
 	public void dispatchWriter(TransportId t, ContactId c,
 			BatchTransportWriter w) {
-		executor.execute(batchConnFactory.createOutgoingConnection(t, c, w));
+		batchConnFactory.createOutgoingConnection(t, c, w);
 	}
 
 	public void dispatchIncomingConnection(TransportId t,
@@ -124,19 +118,11 @@ public class ConnectionDispatcherImpl implements ConnectionDispatcher {
 			s.dispose(false);
 			return;
 		}
-		// Pass the connection to the executor and return
-		Runnable[] r = streamConnFactory.createIncomingConnection(c, s,
-				encryptedIv);
-		assert r.length == 2;
-		executor.execute(r[0]); // Write
-		executor.execute(r[1]); // Read
+		streamConnFactory.createIncomingConnection(c, s, encryptedIv);
 	}
 
 	public void dispatchOutgoingConnection(TransportId t, ContactId c,
 			StreamTransportConnection s) {
-		Runnable[] r = streamConnFactory.createOutgoingConnection(t, c, s);
-		assert r.length == 2;
-		executor.execute(r[0]); // Write
-		executor.execute(r[1]); // Read
+		streamConnFactory.createOutgoingConnection(t, c, s);
 	}
 }
diff --git a/components/net/sf/briar/transport/batch/BatchConnectionFactoryImpl.java b/components/net/sf/briar/transport/batch/BatchConnectionFactoryImpl.java
index bc741c2f6ef348f75a07cbda5975d44168bfd083..d67f109dc6dd1b6dac2a47ec1db0d35144af8733 100644
--- a/components/net/sf/briar/transport/batch/BatchConnectionFactoryImpl.java
+++ b/components/net/sf/briar/transport/batch/BatchConnectionFactoryImpl.java
@@ -5,11 +5,11 @@ import net.sf.briar.api.TransportId;
 import net.sf.briar.api.db.DatabaseComponent;
 import net.sf.briar.api.protocol.ProtocolReaderFactory;
 import net.sf.briar.api.protocol.writers.ProtocolWriterFactory;
+import net.sf.briar.api.transport.BatchConnectionFactory;
 import net.sf.briar.api.transport.BatchTransportReader;
 import net.sf.briar.api.transport.BatchTransportWriter;
 import net.sf.briar.api.transport.ConnectionReaderFactory;
 import net.sf.briar.api.transport.ConnectionWriterFactory;
-import net.sf.briar.api.transport.batch.BatchConnectionFactory;
 
 import com.google.inject.Inject;
 
@@ -33,15 +33,27 @@ class BatchConnectionFactoryImpl implements BatchConnectionFactory {
 		this.protoWriterFactory = protoWriterFactory;
 	}
 
-	public Runnable createIncomingConnection(ContactId c,
+	public void createIncomingConnection(ContactId c,
 			BatchTransportReader r, byte[] encryptedIv) {
-		return new IncomingBatchConnection(connReaderFactory, db,
-				protoReaderFactory, c, r, encryptedIv);
+		final IncomingBatchConnection conn = new IncomingBatchConnection(
+				connReaderFactory, db, protoReaderFactory, c, r, encryptedIv);
+		Runnable read = new Runnable() {
+			public void run() {
+				conn.read();
+			}
+		};
+		new Thread(read).start();
 	}
 
-	public Runnable createOutgoingConnection(TransportId t, ContactId c,
+	public void createOutgoingConnection(TransportId t, ContactId c,
 			BatchTransportWriter w) {
-		return new OutgoingBatchConnection(connWriterFactory, db,
-				protoWriterFactory, t, c, w);
+		final OutgoingBatchConnection conn = new OutgoingBatchConnection(
+				connWriterFactory, db, protoWriterFactory, t, c, w);
+		Runnable write = new Runnable() {
+			public void run() {
+				conn.write();
+			}
+		};
+		new Thread(write).start();
 	}
 }
diff --git a/components/net/sf/briar/transport/batch/IncomingBatchConnection.java b/components/net/sf/briar/transport/batch/IncomingBatchConnection.java
index ec43c1ce5800d7e550d41d29d853b7f38a3886b8..5756a71cd9f4a2a7d848bf4519db938584f8534c 100644
--- a/components/net/sf/briar/transport/batch/IncomingBatchConnection.java
+++ b/components/net/sf/briar/transport/batch/IncomingBatchConnection.java
@@ -18,7 +18,7 @@ import net.sf.briar.api.transport.BatchTransportReader;
 import net.sf.briar.api.transport.ConnectionReader;
 import net.sf.briar.api.transport.ConnectionReaderFactory;
 
-class IncomingBatchConnection implements Runnable {
+class IncomingBatchConnection {
 
 	private static final Logger LOG =
 		Logger.getLogger(IncomingBatchConnection.class.getName());
@@ -42,7 +42,7 @@ class IncomingBatchConnection implements Runnable {
 		this.encryptedIv = encryptedIv;
 	}
 
-	public void run() {
+	void read() {
 		try {
 			byte[] secret = db.getSharedSecret(contactId);
 			ConnectionReader conn = connFactory.createConnectionReader(
diff --git a/components/net/sf/briar/transport/batch/OutgoingBatchConnection.java b/components/net/sf/briar/transport/batch/OutgoingBatchConnection.java
index ad2a7e57e0541b58e62e8e0af060b741bed710f9..6057ac475a1867e83b6522a0916ac894c8984c46 100644
--- a/components/net/sf/briar/transport/batch/OutgoingBatchConnection.java
+++ b/components/net/sf/briar/transport/batch/OutgoingBatchConnection.java
@@ -20,7 +20,7 @@ import net.sf.briar.api.transport.BatchTransportWriter;
 import net.sf.briar.api.transport.ConnectionWriter;
 import net.sf.briar.api.transport.ConnectionWriterFactory;
 
-class OutgoingBatchConnection implements Runnable {
+class OutgoingBatchConnection {
 
 	private static final Logger LOG =
 		Logger.getLogger(OutgoingBatchConnection.class.getName());
@@ -44,7 +44,7 @@ class OutgoingBatchConnection implements Runnable {
 		this.writer = writer;
 	}
 
-	public void run() {
+	void write() {
 		try {
 			byte[] secret = db.getSharedSecret(contactId);
 			long connection = db.getConnectionNumber(contactId, transportId);
diff --git a/components/net/sf/briar/transport/batch/TransportBatchModule.java b/components/net/sf/briar/transport/batch/TransportBatchModule.java
index e6e7c06d4f85eaca44061112d9b9435ca26ef02c..633b4a67e1512ae18d3a74446bfb1529a74aef99 100644
--- a/components/net/sf/briar/transport/batch/TransportBatchModule.java
+++ b/components/net/sf/briar/transport/batch/TransportBatchModule.java
@@ -1,6 +1,6 @@
 package net.sf.briar.transport.batch;
 
-import net.sf.briar.api.transport.batch.BatchConnectionFactory;
+import net.sf.briar.api.transport.BatchConnectionFactory;
 
 import com.google.inject.AbstractModule;
 import com.google.inject.Singleton;
diff --git a/components/net/sf/briar/transport/stream/StreamConnection.java b/components/net/sf/briar/transport/stream/StreamConnection.java
index 652b44c0f1b61b7e7659ff585b24edd89260295e..b0a5325df09ead63152b679d631aab87dc5622a1 100644
--- a/components/net/sf/briar/transport/stream/StreamConnection.java
+++ b/components/net/sf/briar/transport/stream/StreamConnection.java
@@ -94,7 +94,7 @@ abstract class StreamConnection implements DatabaseListener {
 		}
 	}
 
-	public void read() {
+	void read() {
 		try {
 			InputStream in = createConnectionReader().getInputStream();
 			ProtocolReader proto = protoReaderFactory.createProtocolReader(in);
@@ -160,7 +160,7 @@ abstract class StreamConnection implements DatabaseListener {
 		connection.dispose(true);
 	}
 
-	public void write() {
+	void write() {
 		try {
 			OutputStream out = createConnectionWriter().getOutputStream();
 			// Create the packet writers
diff --git a/components/net/sf/briar/transport/stream/StreamConnectionFactoryImpl.java b/components/net/sf/briar/transport/stream/StreamConnectionFactoryImpl.java
index 0bf511f85fbe77bb635ed5cdb5e7fe935983ae76..999d3ee45a360dcdd5129fb341e78e6896beb07c 100644
--- a/components/net/sf/briar/transport/stream/StreamConnectionFactoryImpl.java
+++ b/components/net/sf/briar/transport/stream/StreamConnectionFactoryImpl.java
@@ -7,8 +7,8 @@ import net.sf.briar.api.protocol.ProtocolReaderFactory;
 import net.sf.briar.api.protocol.writers.ProtocolWriterFactory;
 import net.sf.briar.api.transport.ConnectionReaderFactory;
 import net.sf.briar.api.transport.ConnectionWriterFactory;
+import net.sf.briar.api.transport.StreamConnectionFactory;
 import net.sf.briar.api.transport.StreamTransportConnection;
-import net.sf.briar.api.transport.stream.StreamConnectionFactory;
 
 import com.google.inject.Inject;
 
@@ -32,42 +32,42 @@ public class StreamConnectionFactoryImpl implements StreamConnectionFactory {
 		this.protoWriterFactory = protoWriterFactory;
 	}
 
-	public Runnable[] createIncomingConnection(ContactId c,
+	public void createIncomingConnection(ContactId c,
 			StreamTransportConnection s, byte[] encryptedIv) {
 		final StreamConnection conn = new IncomingStreamConnection(
 				connReaderFactory, connWriterFactory, db, protoReaderFactory,
 				protoWriterFactory, c, s, encryptedIv);
-		Runnable[] runnables = new Runnable[2];
-		runnables[0] = new Runnable() {
+		Runnable write = new Runnable() {
 			public void run() {
 				conn.write();
 			}
 		};
-		runnables[1] = new Runnable() {
+		new Thread(write).start();
+		Runnable read = new Runnable() {
 			public void run() {
 				conn.read();
 			}
 		};
-		return runnables;
+		new Thread(read).start();
 	}
 
-	public Runnable[] createOutgoingConnection(TransportId t, ContactId c,
+	public void createOutgoingConnection(TransportId t, ContactId c,
 			StreamTransportConnection s) {
 		final StreamConnection conn = new OutgoingStreamConnection(
 				connReaderFactory, connWriterFactory, db, protoReaderFactory,
 				protoWriterFactory, c, s, t);
-		Runnable[] runnables = new Runnable[2];
-		runnables[0] = new Runnable() {
+		Runnable write = new Runnable() {
 			public void run() {
 				conn.write();
 			}
 		};
-		runnables[1] = new Runnable() {
+		new Thread(write).start();
+		Runnable read = new Runnable() {
 			public void run() {
 				conn.read();
 			}
 		};
-		return runnables;
+		new Thread(read).start();
 	}
 
 }
diff --git a/test/net/sf/briar/transport/batch/BatchConnectionReadWriteTest.java b/test/net/sf/briar/transport/batch/BatchConnectionReadWriteTest.java
index 64caa91e74a913254afc73518ee4fe87996ff64a..a495686c99f7ae7db30275bf5aad45d652ffc546 100644
--- a/test/net/sf/briar/transport/batch/BatchConnectionReadWriteTest.java
+++ b/test/net/sf/briar/transport/batch/BatchConnectionReadWriteTest.java
@@ -109,7 +109,7 @@ public class BatchConnectionReadWriteTest extends TestCase {
 		OutgoingBatchConnection batchOut = new OutgoingBatchConnection(
 				connFactory, db, protoFactory, transportId, contactId, writer);
 		// Write whatever needs to be written
-		batchOut.run();
+		batchOut.write();
 		// Close Alice's database
 		db.close();
 		// Return the contents of the batch connection
@@ -147,7 +147,7 @@ public class BatchConnectionReadWriteTest extends TestCase {
 		// No messages should have been added yet
 		assertFalse(listener.messagesAdded);
 		// Read whatever needs to be read
-		batchIn.run();
+		batchIn.read();
 		// The private message from Alice should have been added
 		assertTrue(listener.messagesAdded);
 		// Close Bob's database