There may be 1000 or more user session active at a given time but not all need DB connection at same time. If any user action requires connection to DB, thead request to pool for connection and complete the work and return the connection to pool as soon as possible. In case no connection is available Connection pool manager will try to make new connetions to DB to fullfill the request. If connection count reaches to max count, requester can wait in queue for some time for connection to be released by some theads. It may timedout after some time and thread will get no connetion available or timed out exception.
Pooling is a trick to manage/share expensive resource. It helps in sharing resource among lots of users. EJB use object pooling in same way. A big family can share two bathrooms. There is no problem if no more than two family members need them at same time. If any memeber needs it and both bathroom is in use, that person have to wait until one is free. There would be exception
in case waiting time is too long. But everything would be fine if family member try to minimize the time spent in bathroom to keep them free as much as possible. It would be very costly to make one bathroom for each memeber
So its important to use these type of resorces carefully. Request connection when you are ready for DB trasaction after all calculations and processing on data is done. Return/close the connection as soon as you are done. Don't wait for garbage collection to close it.
Last thing ..if DB server allows 25 connection max than there is no way more than 25 connection made. But through pooling they can be shared by thousand users.