Semaphore is a class in java.util.concurrent package introduced in JDK 5. Semaphore basically maintains a set of permits, so there are two methods which are mainly used for semaphore.
- acquire
- release
Semaphores are generally used to restrict the number of threads to access resources.
Real time examples:
- Semaphores can be used to restrict number of database connections at a time
- Semaphores can also be used to bound any collection.
Example:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
package org.arpit.java2blog.bean; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.concurrent.Semaphore; public class BoundedArrayList { private final Semaphore semaphore; private List arraylist; BoundedArrayList(int limit) { this.arraylist = Collections.synchronizedList(new ArrayList()); semaphore = new Semaphore(limit); } /* * Add element to the list and call semaphore.acquire method * */ public boolean add(T t) throws InterruptedException { boolean added = false; semaphore.acquire(); try { added = arraylist.add(t); return added; } finally { if (!added) semaphore.release(); } } /* * remove element from the list and call semaphore.release method * */ public boolean remove(T t) { boolean wasRemoved = arraylist.remove(t); if (wasRemoved) semaphore.release(); return wasRemoved; } public void remove(int index) { arraylist.remove(index); semaphore.release(); } public List getArraylist() { return arraylist; } public Semaphore getSemaphore() { return semaphore; } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
package org.arpit.java2blog.bean; public class BoundedArrayListMain { public static void main(String[] args) throws InterruptedException { final BoundedArrayList ba = new BoundedArrayList(5); Runnable runnable1 = new Runnable() { @Override public void run() { try { ba.add("John"); ba.add("Martin"); ba.add("Adam"); ba.add("Prince"); ba.add("Tod"); System.out.println("Available Permits : "+ba.getSemaphore().availablePermits()); ba.add("Tony"); System.out.println("Final list: "+ba.getArraylist()); } catch (InterruptedException ie) { } } }; Runnable runnable2 = new Runnable() { @Override public void run() { try { System.out.println("Before removing elements: "+ ba.getArraylist()); Thread.sleep(5000); ba.remove("Martin"); ba.remove("Adam"); } catch (InterruptedException e) { e.printStackTrace(); } } }; Thread t1 = new Thread(runnable1); Thread t2 = new Thread(runnable2); t1.start(); t2.start(); } } |
1 2 3 4 5 |
Available Permits : 0 Before removing elements: [John, Martin, Adam, Prince, Tod] Final list: [John, Prince, Tod, Tony] |
Explanation:
- We have created two thread t1 and t2.
- t1 and t2 both share common list reference ba.
- When t1 adds 5 elements to the list, available permits became 0.
- Now t1 waits for another thread to remove elements, so that semaphore have some available permits.
- Another thread t2 removes elements from the list after waiting for 5 secs.
- Once t2 removes elements, t1 adds “Tony” to list.
ncie