This document discusses how the Java virtual machine (JVM) maps priorities for threads executing in the JVM (Java threads) onto native thread priorities on Solaris. It covers both current and past implementations of Solaris threads and the JVM.
The JVM defines a range of ten logical priorities for Java threads, including:
java.lang.Thread.MIN_PRIORITY = 1 java.lang.Thread.NORM_PRIORITY = 5 java.lang.Thread.MAX_PRIORITY = 10
 These values [1..10] are passed into Thread.setPriority(int) 
  to assign priorities to Java threads. The default priority of a Java thread 
  is NORM_PRIORITY. (A Java thread that doesn't explicitly call setPriority 
  runs at NORM_PRIORITY.) A JVM is free to implement priorities in 
  any way it chooses, including ignoring the value. 
The Java HotSpot virtual machine currently associates each Java thread with a unique native thread. The relationship between the Java thread and the native thread is stable and persists for the lifetime of the Java thread.
 Prior to Solaris 9 the default libthread was the so-called T1 libthread. 
  T1 provided an M:N threading model where M native threads were multiplexed on 
  top of N kernel threads (LWPs). The relationship between native threads 
  and LWPs was fluid and dynamic and could change even while a thread was running 
  and without the knowledge of the thread. Solaris provided the priocntl() 
  system call to change the dispatching priority of an LWP, but because the relationship 
  between LWPs and native threads was unstable so there was no reliable way to 
  change to change the dispatching priority of a native thread. (The JVM could 
  change the priority of the LWP on which a Java thread was currently running, 
  but the thread could switch to another LWP without the JVM's knowledge). 
T2, the default libthread in Solaris 9 and better, implements a much more simple and robust 1:1 threading model. Each native thread is assigned to a unique LWP, and that relationship is stable for the lifetime of the native thread.
Both T1 and T2 expose a thr_setprio() API that applications use 
  to set a thread's process-local priority. The value assigned by thr_setprio() 
  is a process-local attribute and is not visible to the kernel scheduler. The 
  thr_setprio()-priority controls the placement and ordering of threads 
  on user-level process-local sleep queues, such as the queue of threads associated 
  with a contended process-local mutex. In HotSpot most mutexes are uncontended 
  and condvars have usually have either 0 or 1 threads. As such, the ordering 
  imposed by thr_setprio()-priority has very little effect on most 
  Java threads. The thr_setprio() function supports priority values 
  in the range 0 through 127, inclusive, with 127 representing the highest priority.
T1 also uses thread priority to implement rudimentary user-mode preemption. 
  T1 maintains an invariant that the thr_setprio()-priority of any 
  thread on the local ready queue must be less than or equal to the priority of 
  any unbound thread that's currently running and associated with an LWP. If the 
  invariant is threatened, T1 preempts the lowest priority executing thread to 
  "steal" its LWP in order to reestablish the invariant.
Preemption can occur in these cases:
An early version of T2, referred to as the alternate libthread, appeared in Solaris 8.
For additional information about T1, T2, and LWPs refer to the following:
 In Solaris an LWP's priority influences how many CPU cycles a thread receives 
  relative to other threads. The Solaris scheduler uses priority (among other 
  factors) to determine if one thread should preempt another thread, how often 
  a thread runs, and how long a thread runs. Native LWP priorities are assigned 
  by the priocntl() system call. 
To recap, we have Java threads, with priorities set by the Thread.setPriority 
  method. Java threads run on native threads. The thr_setprio() function 
  is used to change the priority of native threads. Native threads run on LWPs. 
  The priocntl() system call is used to change the priority of LWPs. 
In releases earlier than 1.4.2, when a Java thread called the Thread.setPriority 
  method or when a thread was created, HotSpot would call thr_setprio() 
  to map the Java priority to an native priority. Calling thr_setprio() 
  had very little effect on the execution behavior of of a Java thread. The JVM 
  did not call priocntl() to adjust the priority of the underlying 
  LWP. This was a conscious design decision because in the 1.4.2 time frame the 
  only libthread available on Solaris was the older T1 libthread. 
Note: The JVM could have forced native threads to be bound 1:1 to LWPs under T1 by specifyingTHR_BOUNDwhen threads are created.THR_BOUNDis not sufficient, however, as threads that attach to the JVM might not beTHR_BOUNDand the primordial thread is notTHR_BOUND. Given that there's no way in Solaris to force a thread to be bound after it's been created, the HotSpot implementors decided that it was prudent not to change LWP priority when a Java thread calledsetPriority()
In 1.4.2 HotSpot was able to determine at startup time if it was running under T1 or T2. If the JVM started under T1 the effect of priorities would be precisely the same as in earlier releases.
Under T2, however, 1.4.2 translated calls to the Thread.setPriority 
  method into calls to both thr_setprio() (to change the native process-local 
  priority) and to priocntl() (to change the dispatching priority 
  of the underlying LWP). The JVM called priocntl() only for threads 
  that are running in the TS (timeshare), IA (interactive), and 
  RT (real-time) scheduling classes. Refer to the Solaris priocntl(2) 
  man page for a description of scheduling classes. If a Java thread was not in 
  the TS, IA, or RT scheduling classes the JVM would not attempt to set the priority 
  of the underlying LWP with priocntl().
Unfortunately the default priority of native threads in the TS and IA scheduling 
  classes is the highest possible priority. The default logical priority for Java 
  threads is NORM_PRIORITY, which is midway in domain of Java thread 
  priorities. When the JVM maps NORM_PRIORITY to native and LWP priorities, 
  the outcome is a value that is less then the default native priority. Let's 
  say we have a 2-CPU system running a JVM, and that JVM has two Java threads, 
  both at NORM_PRIORITY. Assume that the threads are in the IA or 
  TS scheduling class, as is commonly the case. When the Java threads are created, 
  the JVM calls priocntl() to map NORM_PRIORITY to the 
  middle of the TS or IA priority bands. Furthermore, assume that 2 native "C" 
  threads in another process are running/ready concurrently with the Java threads. 
  Both the native C threads and the Java threads are CPU-bound and spin, computing. 
  The native threads will run at the highest priority in the TS or IA scheduling 
  class, and the JVM threads will run at the middle priority. Since all four threads 
  are competing for CPU cycles, the native threads will receive relatively more 
  CPU cycles and the Java threads will, in a sense, be disadvantaged. This effect 
  occurs only when Java threads compete with normal threads and the system is 
  entirely saturated. 
Conversely, a benefit of using lower relative priorities is that in the TS and IA scheduling classes a thread running at lower priorities receives a longer quantum, assuming that it's not preempted mid-quantum by higher priority threads that become ready. A longer quantum is often beneficial for threads in server applications as the context switch rate from preemption decreases. A thread is permitted to run on a CPU for a longer period and the cache-reload transient (the period immediately after a thread is scheduled on to a CPU  when a thread incurs a high cache miss rate as it repopulates the CPU's data caches and displaces the previous thread's data) is amortized over a longer quantum.
JRE 5.0 provides the same priority mapping as 1.4.2 except that Java priorities
  in the range [10...5] are all mapped to the highest possible TS or IA priority, 
  while priorities in the range [1..4] are mapped to correspondingly lower native 
  TS or IA priorities. The advantage of this change is that Java threads at NORM_PRIORITY 
  can now compete as expected with native threads. If neither the Java threads 
  nor the native threads have explicitly set priorities (which is commonly the 
  case), both classes of thread will compete on an equal footing, running at the 
  highest priority in the TS or IA scheduling class.
Assuming that Java threads don't explicitly set their priority with setPriority(), 
  this change restores the behavior and effective LWP priority of Java threads 
  that was used prior to 1.4.2. The disadvantage to this implementation is that 
  Java priorities from 5 to 10 are not differentiated. A Java thread at logical 
  priority 8 maps to the same LWP priority as a Java thread at priority 9, for 
  instance. 
The following statements apply to all versions of HotSpot:
Thread.setPriority method may be an expensive operation. 
    Frivolous priority adjustments can reduce performance. NORM_PRIORITY. This, in turn, changes the thread's native 
    priority and potentially changes the priority of the LWP on which the native 
    thread is running. Specifically, if a native thread adjusts its priority and 
    then attaches to a JVM, the JVM overwrites the previous priority settings 
    of the thread. The JVM does not "undo" or restore a native thread's priority 
    if the thread detaches. The Thread.setPriority and Thread.yield methods are 
  advisory. They constitute hints from the application to the JVM. Properly written, 
  robust, platform-independent code can use setPriority() and yield() 
  to optimize the performance of the application, but should not depend on these 
  attributes for correctness. Likewise, no assumptions should be made about the 
  order in which threads are granted ownership of a monitor or the order in which 
  threads wake in response to the notify or notifyAll 
  method. An excellent reference for these topics is Chapter 9, "Threads," 
  in Joshua Bloch's book Effective 
  Java Programming Language Guide.