21st Chapter Concurrency
1. Defining tasks
Task: A task is a piece of code to be executed by a thread of execution. (in C, a piece of code that starts at an address that the function pointer points to)
"Memory Error": The task is not a thread, the thread is used to perform the task. That is, the task is driven by threads. In sequential programming, because there is only one thread of execution, all program code is executed by the execution thread, and all of these program code can be considered a task. Concurrent programming allows us to divide the original large program code into separate, separate parts. Each of these separate parts, called subtasks, can be executed by an execution thread.
Tasks in Java are described by the Runnable interface. The specific task that we are going to perform can be written in the run () method to be handed to a thread for execution.
2. Threads
The light defines the task, and you have to create a thread to execute it. That means you have to associate a task with a thread.
When you create a thread object, you can pass a Runnable object through the thread's constructor to associate the thread with the task.
"Hint": be sure to focus on distinguishing between threads and tasks directly! For a deep understanding of concurrent programming, it is important to differentiate between these two concepts. As mentioned above, if you have multiple thread objects associated with the same task object, data inconsistencies may occur.
3.Executor
The client program only needs to commit the task (that is, the block of code to be executed), regardless of the details of creating the thread, associating the thread with the task, and scheduling the thread. This provides a standard way to decouple the process of submitting a task from the execution of a task. The customer submits the task exactly how to execute, the customer does not have the tube, all is made by the executor. on the one hand, the client does not pay attention to the execution details of the task, on the other hand, because the customer does not need to pay attention to the task execution details, the customer can sit quietly there and so on the results of the task execution, of course, the customer can choose to do other things, once the task execution results come out, we will inform the customer This leads to the concept of asynchronous tasks.
Executor interface has only one method: void execute (Runnable command); Execute the given command at some time in the future
It is obvious that the executor Execute method can only submit tasks that do not return a value, but some tasks will have a return value. The Executorservice interface inherits and extends the executor interface so that tasks with return values can be submitted.
Specific implementation details refer to Threadpoolexecutor class source code.
4. Runnable and callable
Both are used to describe the task. The task described by Runnable does not have a return value, callable is used for a task with a return value, and the calculated results returned by the callable task are saved in the future object. While Runnable does not throw a checked exception, callable may throw an exception.
5. Background Threads
The Setdaemon () method must be called before the thread is started in order to set threads as background threads.
A background thread terminates its run () method without executing a finally clause.
6. Catching exceptions
If an exception is thrown in the run method of a task, it is not used to do try-catch in main, which propagates outward. Solution, create a Thread after calling its Setuncaughtexceptionhandler (Thread.uncaughtexceptionhandler eh) method to set the exception handler.
If you want to use the same exception handler everywhere in your code, you can set up a static domain in the thread class and set the processor as the default uncaught exception handler. Thread.setdefaultuncaughtexceptionhandler (Thread.uncaughtexceptionhandler eh)
7. Resolving shared Resource Competition
Basically all concurrency patterns are in the scenario of "serializing access to shared resources" when resolving thread-conflict issues. means that only one task is allowed to access the shared resource at a given moment.
8. atomicity
For all basic data types except long and double, the JVM can guarantee the atomicity of read and write. It is not guaranteed for long and double because the JVM can execute 64-bit reads and writes as two separate 32-bit operations, where context switching is possible, which is known as a "torn word." When you define long and double variables, you can guarantee the atomicity of read and write if you use the volatile keyword.
[A handful of programmers Daniel can use atomic manipulation instead of synchronization, but only a handful!] ]
9. Visibility
There is also a visibility issue in multiprocessor systems. Changes made by one task may not be visible to other tasks. (modifications may only be stored temporarily in the cache of the local processor.) The synchronization mechanism can not only guarantee the atomicity, but also the guarantee of the visibility!
If there is no synchronization mechanism (this refers to atomic substitution for synchronization), then the visibility of the modification cannot be determined. The volatile keyword also guarantees the visibility of the changes!
[If a domain may be accessed by multiple tasks at the same time, or if at least one of these tasks is a write task, then the domain should be set to volatile. ]
Volatile
If a field's value depends on its previous value (such as an increment counter), volatile does not work.
If the value of a domain is limited by the value of another domain, volatile does not work! [personal opinion that the inability to work here refers to the inability to guarantee visibility.] ]
Volatile is the only safe case where there is only one mutable field in the class.
[The least risky way is to use the Synchronized keyword]
11. Atomic Class
Classes such as Atomicinteger, Atomiclong, Atomicreference, and so on, are used primarily for classes in java.uti.concurrent and for performance calls.
Threadlocal class
The second way to prevent a task from creating a conflict on a shared resource is to eradicate the sharing of variables, and thread-local storage can create different stores for each different thread that uses the same variable.
[the "same variable" above often refers to a field in the Runnable class.) Passing the same runnable instance to two different thread objects, each thread will save a copy of the domain when it accesses the same domain as the same runnable instance. Therefore, the need to threadlocal domain in runnable directly with the static modification is good, there is no need to define an instance variable. ]
The field of the Threadlocal class is usually a static variable, otherwise it is completely unnecessary if it is an instance variable.
13. Interrupts
Blocking methods
When a method throws a interruptedexception, it not only tells you that it can throw a particular check exception, but also tells you something else. For example, it tells you that it is a blocking (blocking) method [that is, calling the method causes the calling thread to be blocked], and if you respond properly, it will try to eliminate blocking and return as early as possible.
The blocking method differs from the usual method of running for a longer period of time . The general method's completion depends only on what it wants to do, and whether there are enough compute resources available (CPU cycles and memory). The completion of the blocking method also depends on some external events, such as timer expiry, I/O completion, or the action of another thread (releasing a lock, setting a flag, or putting a task in a work queue). The general approach ends when their work is done, and the blocking methods are more difficult to predict because they depend on external events. Blocking methods can affect responsiveness because it is difficult to predict when they will end.
Blocking methods can be useful for canceling a blocking method because they cannot be terminated because they cannot wait for the event to wait. A cancel operation refers to an operation that can be terminated externally before it is completed normally. The interrupt mechanism provided by thread and supported by Thread.Sleep () and object.wait () is a cancellation mechanism that allows one thread to request that another thread stop what it is doing. when a method throws Interruptedexception, it is telling you that if the thread that executes the method is interrupted, it will try to stop the thing it is doing while returning early and by throwing a interruptedexception indicating that it returns early . A well-behaved blocking library method should be able to respond to interrupts and throw interruptedexception so that it can be used in a cancel activity without affecting the response.
Thread break
Each thread has a Boolean property associated with it that represents the interrupt state of the thread (interrupted status). When the interrupt state is initially false, one of the following two scenarios occurs when another thread breaks a thread by calling Thread.Interrupt (). If that thread is executing a low-level interruptible blocking method, such as Thread.Sleep (), Thread.Join (), or object.wait (), then it will unblock and throw a interruptedexception. Otherwise, interrupt () simply sets the interrupt state of the thread. Code running in the interrupted thread can then poll the interrupt state to see if it is being requested to stop what it is doing. The interrupt state can be read by thread.isinterrupted () and can be read and purged by an operation called thread.interrupted ().
Interrupts are a collaborative mechanism. When a thread breaks another thread, the interrupted thread does not have to immediately stop what it is doing. Instead, a break is a polite request to another thread to stop what it is doing when it is willing and convenient. Some methods, such as Thread.Sleep (), take such requests very seriously, but each method does not necessarily respond to interrupts. For interrupt requests, a method that does not block but still takes a long time to execute can poll the interrupt state and return early when it is interrupted. You can ignore interrupt requests at will, but doing so can affect the response.
One of the benefits of interrupted collaboration features is that it provides greater flexibility in constructing a removable activity safely. We seldom want an activity to stop immediately, and if the activity is canceled while an update is in progress, the program data structure may be in an inconsistent state. Interrupts allow a removable activity to clean up work in progress, restore invariants, and notify other activities that it will be canceled before terminating.
The above quote: "java Theory and combat: Handling Interruptexception" [IBM developerworks there are many high-quality articles, study well ^_^, here are more Java theory and practical articles ]
(1) How to give the line Cheng interrupt message?
If there is a reference to a thread object, call Thread.Interrupt () directly;
Executor.shutdownnow () invokes the interrupt () method on all objects launched by executor.
What should I do if I want to interrupt a thread in a thread that executor started? The task is submitted through the Executor.submit () method, then a future object is obtained, and the Cancel (true) method is called on the Future object (the parameter value is true).
(2) Not all blockages are interruptible
A. Threads that attempt to perform IO operations are non-interruptible. For example, the read () method of InputStream is blocked until the input data is available, the end of the stream is detected, or an exception is thrown. Calling the interrupt () method on the Process object calling the Read () method will not respond to interrupts.
B. You cannot interrupt the thread that is attempting to acquire a synchronized lock. If an attempt is made to invoke its Synchronized method on an object, and the lock for that object has been acquired by another task, then the calling task will be suspended (blocked) until the lock is available.
Summary: We were able to interrupt the call to sleep (or any call that would throw interruptexception). However, you cannot interrupt a thread that is attempting to acquire a synchronized lock or attempt to perform an IO operation. At any given moment, as long as the task is blocked in a non-disruptive manner, there is a potential for locking the program.
Workaround:
For non-interruptible io, you can close the underlying resource on which the task has been blocked or use NiO (the blocked NIO channel will automatically respond to interrupts);
For threads that attempt to acquire a synchronized lock, you can use Reentrantlock (the task that is blocked on the reentrantlock has the ability to be interrupted).
14. Collaboration between threads
Before dealing with the problem of interference between threads, now consider the problem of collaboration with each other.
[Think in Java] base supplements 4-concurrency