I experienced the exact same problem with the duration of the Thread.sleep(). I fixed it with some retroaction loop to get an average sleep time around what I need to have a stable frame rate around 40fps.
I am using the Direct3d pipelines because I have a ATI graphic card. The openGL pipeline is behaving weird on my config.
I find Java 2D very fast for my game: it is a full screen mode (1024x768) and I can achieve 60 fps without any problem. Just have to make sure we don't break the acceleration. From what I know, the rotation of an image breaks the acceleration so I don't use it. It is very important as well to use compatible images so that they can be accelerated.