Some of the things about Java threading concurrency

Source: Internet
Author: User
Tags instance method scalar terminates thread class volatile home screen

Java Concurrency structure

Original link:


    • Thread
    • Synchronous
    • Monitor

A thread is a sequence of calls that are executed independently, and the threads of the same process share some system resources (such as file handles) at the same time to access the object resources (memory resources) created by the same process. The Java.lang.Thread object is responsible for the statistics and control of this behavior.

Each program has at least one thread-that is, the thread that runs the main class Main method as a Java Virtual machine (JVM) startup parameter. Other background threads may also be started during the initialization of a Java virtual machine. The number and variety of such threads varies depending on the implementation of the JVM. However, all user-level threads are explicitly constructed and are started in the main thread or other user threads.

Here is a summary of the main methods and properties in the thread class and some considerations for use. The content will be discussed further in this book (Java Concurrency constructs). The Java language Specification and the published API documentation will have a more detailed and authoritative description.

Construction method

The different constructor methods in the thread class accept different combinations of the following parameters:

    • A Runnable object, in which case the Thread.Start method will invoke the Run method corresponding to the Runnable object. If the Runnable object is not provided, an default implementation is immediately available.
    • A string string that is used as the thread ID name, which is useful during tracing and debugging, except that it does not.
    • The thread group (Threadgroup), which is used to place the newly created thread, throws a SecurityException if the provided threadgroup is not allowed to be accessed.

The thread class itself already implements the Runnable interface, so in addition to providing a way to execute the Runnable object as a constructor parameter, you can create a subclass of thread that achieves the same effect by overriding its run method. However, a better practice is to define a Runnable object separately and use it as a parameter to construct the method. Dispersing the code in different classes allows the developer to not dwell on internal interactions between the synchronization methods used in the runnable and thread objects or the synchronization blocks. More generally, this separation allows for independent control of the operation itself and the context in which it is run. Better yet, the same Runnable object can be used to initialize other threads at the same time, or to construct a lightweight execution framework (executors). Another thing to mention is that there is a drawback to implementing threading by inheriting the thread class: it makes it impossible to inherit other classes.

The thread object has a daemon (daemon) identity attribute that cannot be assigned in the constructor method, but can be set before the thread is started (via the Setdaemon method). When all non-daemon threads in the program have been terminated, calling the Setdaemon method may cause the virtual machine to brutally terminate the thread and exit. The Isdaemon method can return the value of the property. The role of Daemons is very limited, and even background threads often need to do some cleanup work when the program exits. (Daemon pronunciation is "Day-mon", which is the legacy of system programming, the system daemon is a continuous process, such as printer queue management, it is always running in the system. )

Start thread

Invoking the Start method triggers the thread instance to start its run method with a new thread. The new thread does not hold any synchronization locks on the calling thread.

A thread terminates when a thread runs gracefully or throws some kind of undetected exception (for example, a run-time exception (RuntimeException), a fault (error), or its subclass). After the thread terminates, it cannot be restarted. Calling multiple start methods on the same thread throws a Invalidthreadstateexception exception.

If the thread has started but has not yet terminated, the call to the IsAlive method returns true. Even though the thread is in a blocking (Blocked) state for some reason, the method still returns true. If the thread has been canceled (cancelled), then calling its isalive when it returns false will vary depending on the implementation of each Java virtual machine. There is no way to know if an inactive thread has been started (the translator notes that the thread will return false before and after the start of the run and you will not know the specific state of the thread in false). Another point is that while a thread can know the identity of other threads of the same thread group, it does not know which thread it was called to start with.

Priority level

Java Virtual machines in order to achieve the characteristics of cross-platform (different hardware platforms and various operating systems), the Java language thread scheduling and scheduling fairness has not made any commitment, and even will not strictly guarantee that the threads will be executed. However, Java threads support priority methods that affect the scheduling of threads:

Each thread has a priority, distributed between Thread.min_priority and Thread.max_priority (1 and 10, respectively)
By default, the newly created thread has the same priority as the thread that created it. The initialization thread associated with the main method has a default priority, which is thread.norm_priority (5).
The current priority of a thread can be obtained through the GetPriority method.
The priority of a thread can be dynamically modified by the SetPriority method, and the highest priority of a thread is defined by the thread group in which it resides.

When the number of threads that can be run exceeds the number of available CPUs, the thread scheduler is more inclined to execute threads that have higher priority. The specific strategy varies by platform. For example, some Java virtual machine implementations always choose the highest-priority thread execution. Some virtual machine implementations map 10 priorities in Java to a smaller range of priorities supported by the system, so threads with different priorities may end up being treated equally. There are also virtual opportunities to dynamically adjust thread priorities using aging policies (which increase the priority of threads over time), while other virtual machines implement scheduling policies that ensure that low-priority threads are ultimately able to run. Setting the thread priority can affect scheduling results between programs running on the same machine, but this is not required.

Thread precedence has no effect on righteousness and correctness. In particular, priority management cannot be used to replace locking mechanisms. The priority is only used to indicate which threads are critical, and when there are many threads that are motivated to compete for CPU resources, the thread's priority identification will be very useful. For example, the priority setting of the particle animation thread in Particleapplet is lower than the applet thread that created them, and on some systems the response to mouse clicks can be increased without affecting other features. However, even if the SetPriority method is defined as an empty implementation, the program should be designed to be executed correctly (though it may not be responding).

The following table lists the usual conventions for different types of task thread priority settings. In many concurrent applications, at any given point in time, only a relatively small number of threads are in an executable state (another thread may be blocked for various reasons), in which case there is no reason to manage the priority of the thread. In other cases, tuning on the thread priority may play a role in tuning the concurrency system.

Scope use
Ten Crisis Management (emergency treatment)
7-9 Interactive, Event-driven (interactive correlation, event driven)
4-6 Io-bound (IO restricted Class)
2-3 Background computation (background calculation)
1 run only if nothing else can (runs only when no thread is running)

Control method

Only a few methods can be used to communicate across threads:

    • Each thread has an associated Boolean type of interrupt ID. Thread T up-T.interrupt will set the interrupt identity of the threads to true unless thread t is in Object.wait,thread.sleep, or Thread.Join, In these cases, the interrupt call causes these operations on T to throw interruptedexception exceptions, but the interrupt ID of T is set to false.
    • The interrupt state of any one thread can be obtained by invoking the Isinterrupted method. This method will return true if the thread has been interrupted by the interrupt method.
    • However, calling the Isinterrupted method will throw a Interruptedexception exception if the Thread.interrupted method is called and the interrupt identity has not been reset, or if the thread is in the wait,sleep,join process. Calling the T.join () method suspends execution of the calling thread until the thread T executes: when the T.isalive () method returns False, the call to T.join () will return directly (return). Another join method with parameter milliseconds (millisecond) is called, and if the thread fails to complete within the specified time, the calling thread will regain control. Because of the implementation of the IsAlive method, it makes no sense to call the join method on a thread that has not yet started. Similarly, it is unwise to attempt to invoke the Join method on a thread that has not yet been created.

At first, the thread class also supported some other control methods: Suspend,resume,stop and Destroy. These methods have been declared out of date. Where the Destroy method has never been implemented and is not expected later. There is a lack of security and reliability by using the wait/wake mechanism to increase the suspend and resume methods, which will be discussed in section 3.2. The problem caused by the Stop method will also be discussed in

Static methods

Some of the methods in the thread class are designed to work only on threads that are currently running (that is, the thread that calls the thread method). To emphasize this, these methods are declared static.

    • The Thread.CurrentThread method returns a reference to the current thread, which can be used to invoke other non-static methods, such as Thread.CurrentThread (). GetPriority () returns the priority of the calling thread.
    • The Thread.interrupted method clears the current thread's break state and returns to the previous state. (The interrupt state of a thread is not allowed to be purged by another thread)
    • The Thread.Sleep (long msecs) method causes the thread to pause execution for at least msecs milliseconds.

The Thread.yield method simply suggests that the Java Virtual machine dispatch execution to other threads (if any) that are already in a ready state, rather than the current thread. Ultimately, how the Java virtual machine implements this behavior is entirely up to its liking.

Despite the lack of security, the yield method can still play a real role in the implementation of a single-CPU Java virtual machine that does not support split-time/preemptive-mode thread scheduling. In this case, the thread will be re-dispatched only if it is blocked (for example, waiting for IO, or calling sleep, etc.). On these systems, threads that perform non-blocking, time-consuming computing tasks take up a long time on the CPU, resulting in reduced responsiveness to the application. If a non-blocking, time-consuming computational thread can cause the processing thread or other interactive threads to exceed the tolerable limit, the yield operation (or sleep) may be inserted in it, allowing the thread with the lower thread priority to execute. To avoid unnecessary effects, you can only invoke the yield method by chance, for example, you can insert the following code in a loop: if (Math.random () < 0.01) Thread.yield ();

On Java Virtual machine implementations that support preemptive scheduling, the thread scheduler ignores the yield operation as the most perfect strategy, especially on multicore processors.

Thread Group

Each thread is a member of a thread group. By default, both the new thread and the thread that created it belong to the same thread group. Thread groups are distributed in a tree-like form. When a new thread group is created, this thread group becomes a subgroup of the current thread group. The Getthreadgroup method returns the thread group to which the current thread belongs, and correspondingly, the Threadgroup class has methods to get which threads are currently part of this thread group, such as the enumerate method.

One of the purposes of the Threadgroup class is to support security policies to dynamically restrict the operation of threads to that group. For example, it is illegal to call interrupt on a thread that does not belong to the same group. This is the action taken to avoid certain problems (for example, an applet thread attempting to kill the refresh thread on the home screen). Threadgroup can also set a maximum thread priority for all threads in the group.

Thread groups are often not used directly in the program. In most applications, a common collection class (such as Java.util.Vector) should be a better choice if you are simply tracking the grouping of thread objects in your program.

Of the few methods in the Threadgroup class, the Uncaughtexception method is useful when a thread in a thread group is interrupted by throwing an undetected exception (such as a null pointer exception nullpointerexception). Call this method to print the call stack information for the outgoing thread.

Synchronizing Objects with Locks

Each instance of the object class and its subclasses has a lock. Where scalar type int,float is not an object type, but a scalar type can be used as a lock by its wrapper class. Individual member variables cannot be marked as synchronous. Locks can only be used on methods that use these variables. However, as described on, member variables can be declared volatile, which affects the atomicity, visibility, and ordering of the variable.

Similarly, array objects that hold scalar variable elements have locks, but scalar elements in them do not have locks. (That is, there is no way to declare an array member as a volatile type). If an array is locked, it does not mean that its array members can be locked by atoms. There is also no way to lock multiple objects in an atomic operation.

A class instance is essentially an object. As described below, the lock of the class object is used in the static synchronization method.

Synchronization methods and synchronization blocks

With the Synchronized keyword, there are two syntactic constructs: synchronous code blocks and synchronous methods. The synchronization code block needs to provide an object parameter as a lock. This allows any method to lock any of the one by one objects. But the most common parameter used in a synchronous code block is this.

Synchronous code blocks are thought to be more fundamental than synchronous methods. The following two ways of declaring are equivalent:

1 synchronizedvoidf() { /* body */ }
2 void f() { synchronized(this) { /* body */} }

The Synchronized keyword is not part of the method signature. So when subclasses overwrite synchronous methods in the parent class or synchronous methods declared in the interface, the synchronized modifier is not automatically inherited, and the construction method cannot be truly synchronous (although you can use synchronous blocks in the constructor method).

The synchronous instance method uses the same lock in its subclasses and parent classes. But the synchronization of the inner class method is independent of its outer class, but a non-static inner class method can lock its outer class in this way:

1 synchronized(OuterClass.this) { /* body */}
Wait for lock and release lock

Use the Synchronized keyword to follow a set of built-in lock-wait-release mechanisms. All locks are block-structured. The lock must be obtained when entering a synchronous method or synchronization block, and the lock must be released when exiting (even if an exception exits). You can't forget to release the lock.

The lock operation is based on a separate thread rather than on a separate call. The condition that a thread is able to enter a synchronous code is that the current lock is not occupied or the current thread is already occupying the lock, otherwise the thread will block. (This reentrant or recursive lock is different from the POSIX thread). This allows a synchronous method to directly invoke another synchronization method of the same lock management without having to be frozen (note: There is no need to go through the release lock-block-Request lock process).

The synchronization method or synchronization block follows the mechanism of this lock acquisition/Lock release, which is that all synchronous methods or synchronization blocks are on the same lock object. If a synchronization method is in progress, other non-synchronous methods can be executed at any time. In other words, synchronization is not equal to atomicity, but the synchronization mechanism can be used to achieve atomicity.

When a thread releases a lock, another thread may be waiting for the lock (or possibly the same thread, because the thread may need to enter another synchronization method). However, there is no guarantee as to which thread will be able to obtain this lock immediately and when. (That is, there is no guarantee of fairness-see In addition, there is no way to get a given lock is being owned by which thread.

As 2.2.7 discusses, synchronization can have side effects on the underlying memory system in addition to lock control.

Static Variables/methods

Locking an object does not atomically protect the static member variable of the object class or its parent class. Instead, you should ensure access to a static member variable by synchronizing a static method or block of code. Static synchronization uses locks that are owned by class objects that have static method lock declarations. The static lock of Class C can be obtained by using the built-in instance method:
Synchronized (C.class) {/* body */}

The static locks that correspond to each class have no relation to other classes, including their parent classes. It is not valid to attempt to protect a static member variable in a parent class by adding a static synchronization method to the subclass. An explicit block of code should be used instead.

The following approach is also a bad practice:
Synchronized (GetClass ()) {/* body */}//Do not use
In this way, the actual class that may be locked is not the class that corresponds to the static member variable that needs to be protected (possibly its subclass)

The Java Virtual machine obtains and frees class locks internally during class loading and class initialization. Unless you are going to write a special class loader or need to use multiple locks to control the static initial order, these internal mechanisms should not interfere with the use of synchronous methods and synchronization blocks of ordinary class objects. There is no internal action on the Java Virtual machine to get the lock of the class object you create and use independently. However, when you inherit java.* classes, you need to be particularly careful about the locking mechanisms used in these classes.


Just as each object has a lock, each object has a waiting set managed by these methods (Wait,notify,notifyall,thread,interrupt). Entities that have locks and wait collections are often referred to as monitors (although each language defines slightly different details), any object can be used as a monitor.

The wait collection for an object is managed by a Java virtual machine. Each waiting set holds a blocking thread that waits on the current object but has not yet been woken up or released.

Because the method that interacts with the wait set (Wait,notify,notifyall) is called only if it has a lock on the target object, it is not possible to verify its correctness during the compilation phase. But a bad operation at run time causes the Illegalmonitorstateexception exception to be thrown.

The operations of these methods are described as follows:

Calling the wait method will result in the following actions:

    • If the current thread has been terminated, this method exits immediately and throws a Interruptedexception exception. Otherwise the current thread will go into a blocking state.
    • The Java Virtual machine places the thread in the waiting collection of the target object.
    • Releases the synchronization lock for the target object, but other locks are still held by the thread. Even if a synchronous call is nested more than once on the target object, the held reentrant lock is completely freed. This way, the current lock state can be fully restored when the back is restored.

Calling notify will result in the following actions:

    • The Java Virtual machine randomly selects a thread from the waiting set of the target object (called T, as long as it waits for one or more threads in the collection) and removes t from the Wait collection. When there are multiple threads waiting in the collection, there is no mechanism to guarantee which thread will be selected.
    • The thread t must regain the lock of the target object until the thread calls notify to release the lock, otherwise it will block. If another line enters upgradeable the lock, thread T will continue to enter the blocking state.
    • Thread T resumes execution from the point at which it was previously wait.


The Notifyall method is the same as the operating mechanism of the Notify method, except that these processes occur on all threads in the object's waiting set (in fact, it happens at the same time). But because these threads all need to get the same lock, eventually only one thread can continue to execute.

Interrupt (interrupt)
If you call the Thread.Interrupt method on a thread that is interrupted by wait, the processing mechanism and the notify mechanism are the same, but after the lock is re-acquired, the method throws an Interruptedexception exception and the thread's interrupt ID is set to False. If the interrupt operation occurs at the same time as a notify operation, there is no guarantee that the operation will be executed first, so any result is possible. (future versions of JLS may provide deterministic assurance of these operational results)

Timed Wait (timed wait)
The timer version of the Wait method, wait (long mesecs), and wait (long Msecs,int nanosecs), parameters specify the maximum time value that needs to wait in the wait collection. If it is not awakened within the time limit, it will be released automatically, except that the other operations are the same as the no-parameter wait method. There is no state to indicate the difference between a thread's normal wakeup and a timeout wakeup. It is important to note that the wait (0) and Wait (0,0) methods actually have a special meaning, which is equivalent to an unlimited wait () method, which may be contrary to your intuition.

Due to the thread competition, scheduling policy and the granularity of the timer, the timing wait method may consume any time. (Note: There is no guarantee on the granularity of the timer, most of the Java Virtual Machine implementations are currently implemented when the parameter setting is less than 1 milliseconds, the observed result is basically between 1~20 milliseconds)

The Thread.Sleep (long msecs) method uses the Wait method for timed waits, but does not use a synchronous lock on the current object. Its effect is described as follows:
if (msecs! = 0) {
Object s = new Object ();
Synchronized (s) {s.wait (msecs);}
Of course, the system does not need to use this method to implement the Sleep method. It should be noted that the sleep (0) method means that the break-in process is at least 0 times, and can be interpreted casually. (Translator Note: This method has a special role, from the principle that it can cause the system to re-compete with the CPU).

Some of the things about Java threading concurrency

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.