Concurrent blocking stack
There is only one concern for me: you should not allow to instantiate the object with max elements below 0 (IllegalArgumentException ). Therefore a proper handling for this situation in your methods has to be made to avoid a neverending blocking. I suggest to return null.

Expecting a timout for your poll-method may be beneficial in several situations. Concurrent implementations of the Java API do define both: a non-argument poll-method and one with a timeout. But I do not see this as mandatory.

Some developers will suggest to make synchronization intransparent to the user of your class introducing an internal lock object and mention thread-safety in JavaDoc. They argue with "defensive programming" to prevent deadlocks. My personal opinion to that: You send the wrong message to the using developer.

Don't get me wrong: Preventing deadlocks is important. But it is more important to know what to do when. That is known as competence. Preventing others to make mistakes is ok. That can be done in several ways. But others to allow a lack of competence is exactly the message you would send. You would try to solve a potential future errors that are not your business. On the other side you allow misusage of objects without habing the other force to correct thhis. My way is: If someone is doing strange things with objects he doesn't own he either should know exactly what he is doing or handle occuring errors and deadlocks. You should know that this is how the majority of developers will NOT argue.