Java threads are generally preemptive between priorities. A higher priority thread takes precedence over a lower priority thread. If a higher priority thread goes to sleep or blocks, then a lower priority thread can be run (assuming one is available and ready to be run). However, as soon as the higher priority thread wakes up or unblocks, it will interrupt the lower priority thread and run until it finishes, it or blocks again, or until it is preempted by an even higher priority thread.
The Java Language Specification allows VMs to occasionally run a lower priority thread instead of a runnable higher priority thread, but in practice this is unusual.
However, nothing in the Java Language Specification specifies what is supposed to happen with equal priority threads. On some systems these threads will be time-sliced, and the runtime will allot a certain amount of time to a thread. When that time is up, the runtime preempts the running thread and switches to the next thread with the same priority. On other systems, a running thread will not be preempted in favor of a thread with the same priority. It will continue to run until it blocks, explicitly yields control, or is preempted by a higher priority thread.