Requirements for Resource Pool:
- Allow threads to access resources concurrently
- Should block threads if no resource is available at the moment
- Maintain a pool of initialized resources to allow reuse and avoid costly initialization of resources
- ConcurrentLinkedQueue - An unbounded thread-safe queue. This collection is ideal to act as container of resources since it provides concurrent non blocking access to its elements.
- Semaphore - Semaphore maintains a set of permits by having a counter. This can be used to acquire or release a permit. If no permits are available then acquire() blocks the invoking thread.