// ======================================================================== // Copyright (c) 2004-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.util.thread; import static org.junit.Assert.assertTrue; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; import junit.framework.Assert; import org.junit.Test; public class QueuedThreadPoolTest { final AtomicInteger _jobs=new AtomicInteger(); class RunningJob implements Runnable { private final CountDownLatch _run = new CountDownLatch(1); private final CountDownLatch _stopping = new CountDownLatch(1); private final CountDownLatch _stopped = new CountDownLatch(1); public void run() { try { _run.countDown(); _stopping.await(); } catch(Exception e) { e.printStackTrace(); } finally { _jobs.incrementAndGet(); _stopped.countDown(); } } public void stop() throws InterruptedException { _run.await(10,TimeUnit.SECONDS); _stopping.countDown(); if (!_stopped.await(10,TimeUnit.SECONDS)) throw new IllegalStateException(); } }; @Test public void testThreadPool() throws Exception { QueuedThreadPool tp= new QueuedThreadPool(); tp.setMinThreads(5); tp.setMaxThreads(10); tp.setMaxIdleTimeMs(1000); tp.setThreadsPriority(Thread.NORM_PRIORITY-1); tp.start(); waitForThreads(tp,5); waitForIdle(tp,5); Thread.sleep(1000); waitForThreads(tp,5); waitForIdle(tp,5); RunningJob job=new RunningJob(); tp.dispatch(job); waitForIdle(tp,4); waitForThreads(tp,5); job.stop(); waitForIdle(tp,5); waitForThreads(tp,5); Thread.sleep(200); waitForIdle(tp,5); waitForThreads(tp,5); RunningJob[] jobs = new RunningJob[5]; for (int i=0;i<jobs.length;i++) { jobs[i]=new RunningJob(); tp.dispatch(jobs[i]); } waitForIdle(tp,0); waitForThreads(tp,5); job=new RunningJob(); tp.dispatch(job); waitForThreads(tp,6); job.stop(); waitForThreads(tp,5); jobs[0].stop(); waitForIdle(tp,1); waitForThreads(tp,5); for (int i=1;i<jobs.length;i++) jobs[i].stop(); waitForIdle(tp,5); waitForThreads(tp,5); jobs = new RunningJob[15]; for (int i=0;i<jobs.length;i++) { jobs[i]=new RunningJob(); tp.dispatch(jobs[i]); } waitForIdle(tp,0); waitForThreads(tp,10); for (int i=0;i<9;i++) jobs[i].stop(); waitForThreads(tp,9); for (int i=9;i<jobs.length;i++) jobs[i].stop(); waitForIdle(tp,5); tp.stop(); } @Test public void testShrink() throws Exception { final AtomicInteger sleep = new AtomicInteger(100); Runnable job = new Runnable() { public void run() { try { Thread.sleep(sleep.get()); } catch(Exception e) { e.printStackTrace(); } } }; QueuedThreadPool tp= new QueuedThreadPool(); tp.setMinThreads(2); tp.setMaxThreads(10); tp.setMaxIdleTimeMs(400); tp.setThreadsPriority(Thread.NORM_PRIORITY-1); tp.start(); waitForIdle(tp,2); waitForThreads(tp,2); sleep.set(200); tp.dispatch(job); tp.dispatch(job); for (int i=0;i<20;i++) tp.dispatch(job); waitForThreads(tp,10); waitForIdle(tp,0); sleep.set(5); for (int i=0;i<500;i++) { tp.dispatch(job); Thread.sleep(10); } waitForThreads(tp,2); waitForIdle(tp,2); } @Test public void testMaxStopTime() throws Exception { QueuedThreadPool tp= new QueuedThreadPool(); tp.setMaxStopTimeMs(500); tp.start(); tp.dispatch(new Runnable(){ public void run () { while (true) { try { Thread.sleep(10000); } catch (InterruptedException ie) {} } } }); long beforeStop = System.currentTimeMillis(); tp.stop(); long afterStop = System.currentTimeMillis(); assertTrue(tp.isStopped()); assertTrue(afterStop - beforeStop < 1000); } private void waitForIdle(QueuedThreadPool tp, int idle) { long now=System.currentTimeMillis(); long start=now; while (tp.getIdleThreads()!=idle && (now-start)<10000) { try { Thread.sleep(10); } catch(InterruptedException e) {} } Assert.assertEquals(idle,tp.getIdleThreads()); } private void waitForThreads(QueuedThreadPool tp, int threads) { long now=System.currentTimeMillis(); long start=now; while (tp.getThreads()!=threads && (now-start)<10000) { try { Thread.sleep(10); } catch(InterruptedException e) {} now=System.currentTimeMillis(); } Assert.assertEquals(threads,tp.getThreads()); } }