semaphores (#2198)
* minor logging fix * spring security sso * use basic auth * use form login * cleanup * cleanup * final cleanup * second client app for sso * spring boot bootstrap * add logic * cleanup * add simple controller * add thymeleaf and security * minor fix * minor fix * add more boot properties * fix live test * fix live test * minor fix * semaphores
This commit is contained in:
		
							parent
							
								
									7c6a08746e
								
							
						
					
					
						commit
						20669dc6a1
					
				| @ -0,0 +1,31 @@ | |||||||
|  | package com.baeldung.concurrent.semaphores; | ||||||
|  | 
 | ||||||
|  | import java.util.concurrent.Semaphore; | ||||||
|  | 
 | ||||||
|  | public class CounterUsingMutex { | ||||||
|  | 
 | ||||||
|  |     private final Semaphore mutex; | ||||||
|  |     private int count; | ||||||
|  | 
 | ||||||
|  |     public CounterUsingMutex() { | ||||||
|  |         mutex = new Semaphore(1); | ||||||
|  |         count = 0; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public void increase() throws InterruptedException { | ||||||
|  |         mutex.acquire(); | ||||||
|  |         this.count = this.count + 1; | ||||||
|  |         Thread.sleep(1000); | ||||||
|  |         mutex.release(); | ||||||
|  | 
 | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public int getCount() { | ||||||
|  |         return this.count; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public boolean hasQueuedThreads() { | ||||||
|  |         return mutex.hasQueuedThreads(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | } | ||||||
| @ -0,0 +1,23 @@ | |||||||
|  | package com.baeldung.concurrent.semaphores; | ||||||
|  | 
 | ||||||
|  | import java.util.concurrent.TimeUnit; | ||||||
|  | 
 | ||||||
|  | import org.apache.commons.lang3.concurrent.TimedSemaphore; | ||||||
|  | 
 | ||||||
|  | public class DelayQueueUsingTimedSemaphore { | ||||||
|  | 
 | ||||||
|  |     private final TimedSemaphore semaphore; | ||||||
|  | 
 | ||||||
|  |     public DelayQueueUsingTimedSemaphore(long period, int slotLimit) { | ||||||
|  |         semaphore = new TimedSemaphore(period, TimeUnit.SECONDS, slotLimit); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public boolean tryAdd() { | ||||||
|  |         return semaphore.tryAcquire(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public int availableSlots() { | ||||||
|  |         return semaphore.getAvailablePermits(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | } | ||||||
| @ -0,0 +1,25 @@ | |||||||
|  | package com.baeldung.concurrent.semaphores; | ||||||
|  | 
 | ||||||
|  | import java.util.concurrent.Semaphore; | ||||||
|  | 
 | ||||||
|  | public class LoginQueueUsingSemaphore { | ||||||
|  | 
 | ||||||
|  |     private final Semaphore semaphore; | ||||||
|  | 
 | ||||||
|  |     public LoginQueueUsingSemaphore(int slotLimit) { | ||||||
|  |         semaphore = new Semaphore(slotLimit); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public boolean tryLogin() { | ||||||
|  |         return semaphore.tryAcquire(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public void logout() { | ||||||
|  |         semaphore.release(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public int availableSlots() { | ||||||
|  |         return semaphore.availablePermits(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | } | ||||||
| @ -0,0 +1,140 @@ | |||||||
|  | package com.baeldung.concurrent.semaphores; | ||||||
|  | 
 | ||||||
|  | import static org.junit.Assert.assertEquals; | ||||||
|  | import static org.junit.Assert.assertFalse; | ||||||
|  | import static org.junit.Assert.assertTrue; | ||||||
|  | 
 | ||||||
|  | import java.util.concurrent.ExecutorService; | ||||||
|  | import java.util.concurrent.Executors; | ||||||
|  | import java.util.stream.IntStream; | ||||||
|  | 
 | ||||||
|  | import org.junit.Test; | ||||||
|  | 
 | ||||||
|  | public class SemaphoresManualTest { | ||||||
|  | 
 | ||||||
|  |     // ========= login queue ====== | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     public void givenLoginQueue_whenReachLimit_thenBlocked() { | ||||||
|  |         final int slots = 10; | ||||||
|  |         final ExecutorService executorService = Executors.newFixedThreadPool(slots); | ||||||
|  |         final LoginQueueUsingSemaphore loginQueue = new LoginQueueUsingSemaphore(slots); | ||||||
|  |         IntStream.range(0, slots) | ||||||
|  |             .forEach(user -> executorService.execute(new Runnable() { | ||||||
|  |                 @Override | ||||||
|  |                 public void run() { | ||||||
|  |                     loginQueue.tryLogin(); | ||||||
|  |                 } | ||||||
|  |             })); | ||||||
|  |         executorService.shutdown(); | ||||||
|  | 
 | ||||||
|  |         assertEquals(0, loginQueue.availableSlots()); | ||||||
|  |         assertFalse(loginQueue.tryLogin()); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     public void givenLoginQueue_whenLogout_thenSlotsAvailable() { | ||||||
|  |         final int slots = 10; | ||||||
|  |         final ExecutorService executorService = Executors.newFixedThreadPool(slots); | ||||||
|  |         final LoginQueueUsingSemaphore loginQueue = new LoginQueueUsingSemaphore(slots); | ||||||
|  |         IntStream.range(0, slots) | ||||||
|  |             .forEach(user -> executorService.execute(new Runnable() { | ||||||
|  |                 @Override | ||||||
|  |                 public void run() { | ||||||
|  |                     loginQueue.tryLogin(); | ||||||
|  |                 } | ||||||
|  |             })); | ||||||
|  |         executorService.shutdown(); | ||||||
|  | 
 | ||||||
|  |         assertEquals(0, loginQueue.availableSlots()); | ||||||
|  |         loginQueue.logout(); | ||||||
|  |         assertTrue(loginQueue.availableSlots() > 0); | ||||||
|  |         assertTrue(loginQueue.tryLogin()); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     // ========= delay queue ======= | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     public void givenDelayQueue_whenReachLimit_thenBlocked() { | ||||||
|  |         final int slots = 50; | ||||||
|  |         final ExecutorService executorService = Executors.newFixedThreadPool(slots); | ||||||
|  |         final DelayQueueUsingTimedSemaphore delayQueue = new DelayQueueUsingTimedSemaphore(1, slots); | ||||||
|  |         IntStream.range(0, slots) | ||||||
|  |             .forEach(user -> executorService.execute(new Runnable() { | ||||||
|  |                 @Override | ||||||
|  |                 public void run() { | ||||||
|  |                     delayQueue.tryAdd(); | ||||||
|  |                 } | ||||||
|  |             })); | ||||||
|  |         executorService.shutdown(); | ||||||
|  | 
 | ||||||
|  |         assertEquals(0, delayQueue.availableSlots()); | ||||||
|  |         assertFalse(delayQueue.tryAdd()); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     public void givenDelayQueue_whenTimePass_thenSlotsAvailable() throws InterruptedException { | ||||||
|  |         final int slots = 50; | ||||||
|  |         final ExecutorService executorService = Executors.newFixedThreadPool(slots); | ||||||
|  |         final DelayQueueUsingTimedSemaphore delayQueue = new DelayQueueUsingTimedSemaphore(1, slots); | ||||||
|  |         IntStream.range(0, slots) | ||||||
|  |             .forEach(user -> executorService.execute(new Runnable() { | ||||||
|  |                 @Override | ||||||
|  |                 public void run() { | ||||||
|  |                     delayQueue.tryAdd(); | ||||||
|  |                 } | ||||||
|  |             })); | ||||||
|  |         executorService.shutdown(); | ||||||
|  | 
 | ||||||
|  |         assertEquals(0, delayQueue.availableSlots()); | ||||||
|  |         Thread.sleep(1000); | ||||||
|  |         assertTrue(delayQueue.availableSlots() > 0); | ||||||
|  |         assertTrue(delayQueue.tryAdd()); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     // ========== mutex ======== | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     public void whenMutexAndMultipleThreads_thenBlocked() throws InterruptedException { | ||||||
|  |         final int count = 5; | ||||||
|  |         final ExecutorService executorService = Executors.newFixedThreadPool(count); | ||||||
|  |         final CounterUsingMutex counter = new CounterUsingMutex(); | ||||||
|  |         IntStream.range(0, count) | ||||||
|  |             .forEach(user -> executorService.execute(new Runnable() { | ||||||
|  |                 @Override | ||||||
|  |                 public void run() { | ||||||
|  |                     try { | ||||||
|  |                         counter.increase(); | ||||||
|  |                     } catch (final InterruptedException e) { | ||||||
|  |                         e.printStackTrace(); | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |             })); | ||||||
|  |         executorService.shutdown(); | ||||||
|  | 
 | ||||||
|  |         assertTrue(counter.hasQueuedThreads()); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     public void givenMutexAndMultipleThreads_ThenDelay_thenCorrectCount() throws InterruptedException { | ||||||
|  |         final int count = 5; | ||||||
|  |         final ExecutorService executorService = Executors.newFixedThreadPool(count); | ||||||
|  |         final CounterUsingMutex counter = new CounterUsingMutex(); | ||||||
|  |         IntStream.range(0, count) | ||||||
|  |             .forEach(user -> executorService.execute(new Runnable() { | ||||||
|  |                 @Override | ||||||
|  |                 public void run() { | ||||||
|  |                     try { | ||||||
|  |                         counter.increase(); | ||||||
|  |                     } catch (final InterruptedException e) { | ||||||
|  |                         e.printStackTrace(); | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |             })); | ||||||
|  |         executorService.shutdown(); | ||||||
|  |         assertTrue(counter.hasQueuedThreads()); | ||||||
|  |         Thread.sleep(5000); | ||||||
|  |         assertFalse(counter.hasQueuedThreads()); | ||||||
|  |         assertEquals(count, counter.getCount()); | ||||||
|  |     } | ||||||
|  | } | ||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user