diff --git a/components/net/sf/briar/db/DatabaseCleanerImpl.java b/components/net/sf/briar/db/DatabaseCleanerImpl.java
index 39e6c70b47c85774fb3e80b4596f6ef73516fe4c..71574267edf86ac0820520838905a6dd02deb365 100644
--- a/components/net/sf/briar/db/DatabaseCleanerImpl.java
+++ b/components/net/sf/briar/db/DatabaseCleanerImpl.java
@@ -1,56 +1,45 @@
 package net.sf.briar.db;
 
+import java.util.Timer;
+import java.util.TimerTask;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
 import net.sf.briar.api.db.DbException;
 
-class DatabaseCleanerImpl implements DatabaseCleaner, Runnable {
+class DatabaseCleanerImpl extends TimerTask implements DatabaseCleaner {
 
 	private static final Logger LOG =
-		Logger.getLogger(DatabaseCleanerImpl.class.getName());
+			Logger.getLogger(DatabaseCleanerImpl.class.getName());
 
-	private Callback callback = null;
-	private long msBetweenSweeps = 0L;
-	private boolean stopped = false;
+	private volatile Callback callback = null;
+	private volatile Timer timer = null;
 
-	public synchronized void startCleaning(Callback callback,
-			long msBetweenSweeps) {
+	public void startCleaning(Callback callback, long msBetweenSweeps) {
 		this.callback = callback;
-		this.msBetweenSweeps = msBetweenSweeps;
-		new Thread(this).start();
+		timer = new Timer();
+		timer.scheduleAtFixedRate(this, 0L, msBetweenSweeps);
 	}
 
-	public synchronized void stopCleaning() {
-		stopped = true;
-		notifyAll();
+	public void stopCleaning() {
+		if(timer == null) throw new IllegalStateException();
+		timer.cancel();
 	}
 
 	public void run() {
-		while(true) {
-			synchronized(this) {
-				if(stopped) return;
-				try {
-					if(callback.shouldCheckFreeSpace()) {
-						callback.checkFreeSpaceAndClean();
-					} else {
-						try {
-							wait(msBetweenSweeps);
-						} catch(InterruptedException e) {
-							if(LOG.isLoggable(Level.INFO))
-								LOG.info("Interrupted while waiting to clean");
-							Thread.currentThread().interrupt();
-							return;
-						}
-					}
-				} catch(DbException e) {
-					if(LOG.isLoggable(Level.WARNING))
-						LOG.warning(e.toString());
-				} catch(RuntimeException e) {
-					if(LOG.isLoggable(Level.WARNING))
-						LOG.warning(e.toString());
-				}
+		if(callback == null) throw new IllegalStateException();
+		try {
+			if(callback.shouldCheckFreeSpace()) {
+				callback.checkFreeSpaceAndClean();
 			}
+		} catch(DbException e) {
+			if(LOG.isLoggable(Level.WARNING))
+				LOG.warning(e.toString());
+			throw new Error(e); // Kill the application
+		} catch(RuntimeException e) {
+			if(LOG.isLoggable(Level.WARNING))
+				LOG.warning(e.toString());
+			throw new Error(e); // Kill the application
 		}
 	}
 }
diff --git a/test/net/sf/briar/db/DatabaseCleanerImplTest.java b/test/net/sf/briar/db/DatabaseCleanerImplTest.java
index 9a79bc762cb8532bcf26a5c627dfda84691b00b9..402674954a82dac870f6b1776cb046f0f37df78c 100644
--- a/test/net/sf/briar/db/DatabaseCleanerImplTest.java
+++ b/test/net/sf/briar/db/DatabaseCleanerImplTest.java
@@ -11,29 +11,51 @@ import org.junit.Test;
 
 public class DatabaseCleanerImplTest extends BriarTestCase {
 
+	@Test
+	public void testCleanerRunsPeriodically() throws Exception {
+		final CountDownLatch latch = new CountDownLatch(5);
+		Callback callback = new Callback() {
+
+			public void checkFreeSpaceAndClean() throws DbException {
+				latch.countDown();
+			}
+
+			public boolean shouldCheckFreeSpace() {
+				return true;
+			}
+		};
+		DatabaseCleanerImpl cleaner = new DatabaseCleanerImpl();
+		// Start the cleaner
+		cleaner.startCleaning(callback, 10L);
+		// The database should be cleaned five times (allow 5s for system load)
+		assertTrue(latch.await(5, TimeUnit.SECONDS));
+		// Stop the cleaner
+		cleaner.stopCleaning();
+	}
+
 	@Test
 	public void testStoppingCleanerWakesItUp() throws Exception {
 		final CountDownLatch latch = new CountDownLatch(1);
 		Callback callback = new Callback() {
 
 			public void checkFreeSpaceAndClean() throws DbException {
-				throw new IllegalStateException();
+				latch.countDown();
 			}
 
 			public boolean shouldCheckFreeSpace() {
-				latch.countDown();
-				return false;
+				return true;
 			}
 		};
 		DatabaseCleanerImpl cleaner = new DatabaseCleanerImpl();
 		long start = System.currentTimeMillis();
-		// Start the cleaner and check that shouldCheckFreeSpace() is called
-		cleaner.startCleaning(callback, 30L * 1000L);
+		// Start the cleaner
+		cleaner.startCleaning(callback, 10L * 1000L);
+		// The database should be cleaned once at startup
 		assertTrue(latch.await(5, TimeUnit.SECONDS));
 		// Stop the cleaner (it should be waiting between sweeps)
 		cleaner.stopCleaning();
 		long end = System.currentTimeMillis();
-		// Check that much less than 30 seconds expired
+		// Check that much less than 10 seconds expired
 		assertTrue(end - start < 10L * 1000L);
 	}
 }