What is a process?
A process is a task in the operating system that is an area of memory that contains some resources. A process can contain one or more execution units called threads, which can be seen as executing at the same time (actually taking CPU resources in turn, switching quickly to seemingly simultaneous execution). Each process also has a private virtual address space that can only be accessed by the included thread. When the operating system creates a process, the process automatically requests a thread called the main thread.
What is a thread?
A thread is a sequence of processes that executes a stream, and a homogeneous thread can share a piece of memory space and a set of system resources. Threads are very small when switching, so threads are also becoming light processes. A process can contain multiple sets of threads.
What is the difference between a process and a thread?
A process has at least one thread, and the thread has a smaller scale than the process. Because each process has a separate unit of memory during execution, the process consumes a lot of resources when switching. While multiple threads share this memory, there is no need to switch the memory unit during the thread switching process, so the operation efficiency is greatly improved. The meaning of multithreading is that in an application, there are multiple execution parts that can be executed concurrently. However, the operating system does not consider these threads as standalone programs for process scheduling and resource allocation.
Concurrency and parallelism?
Multiple threads are executed at the same time, which is only seen on the macro level. The fact is that the OS divides the CPU run time into many time slices, gets the time slice of the thread to execute, and waits for the other threads. Because the switching speed is very fast, so the macro is performed simultaneously, but the microscopic is not, this is called concurrency. Parallel execution is performed at the same time, both micro and macro, where parallel programs can be implemented by multiple CPUs.
Create thread create thread and start thread using thread
Define a specific thread by inheriting the thread class and overriding the Run method in the thread class. The purpose of overriding the Run method is to define the logic that the thread executes. The startup thread is not called the Run method, but instead calls the thread's start () method. The start () method takes a thread into the thread dispatch sequence, which is available for execution after the current thread acquires a time fragment. The thread class is a thread class, and each instance represents a thread that can run concurrently.
Class Samplethread extends thread {public void run () {System.out.println ("Override the Run method by inheriting the thread Class");} public static void Main (string[] args) {samplethread thread = new Samplethread (); Thread.Start ();}}
Create and start a thread using runnable
Implement the Runnable interface and override the Run method to define the thread body, and then create the thread to pass the runnable instance into and start the thread. The benefit of this is to reduce coupling by separating the definition thread from the task that the thread will perform. Also, Java is single-inheritance, and if a class inherits the thread class, it cannot inherit other classes. (The thread class also implements the Runnable interface)
In the Runnable interface, only the abstract run method is defined:
public abstract void run ();
Class Samplethread implements Runnable {public void run () {System.out.println ("overriding the Run method by inheriting the thread Class");} public static void Main (string[] args) {Samplethread sample = new Samplethread (); Thread thread = new thread (sample); Thread.Start ();}}
Create a thread with an anonymous inner class
Thread thread = new Thread () {public void Run () {};};
Break Thread in
The thread terminates when the Run method is executed, or the exception is not caught. However, if you want to force a thread to terminate, you can use the interrupt method to request a terminating thread.
A thread break is a change in the interrupt state of a thread, which may be death after an outage, may be waiting for a new task, or it may proceed to the next step, which depends on the program itself. The thread will constantly detect this interrupt identifier bit to determine if it should be interrupted. However, if the thread is blocked, terminating the thread with interrupt throws a Interruptedexception exception.
Use isinterrupted to detect if a thread is interrupted
Boolean isinterrupted ()
Boolean interrupted (): Tests if the front thread is interrupted, but this call has a side effect, and he sets the current interrupt state to False
void Interrupt (): Send interrupt request, interrupt status is set to True
Thread state
A thread can have a status of 6:
NEW: Newly Created
Runnable: Can be run
Blocked: Blocked
Waiting: Waiting
Timed Waiting: Timed Wait
Terminated: Was terminated
Detecting current thread state through the GetState () method
New Thread creation
Create a thread using the new operator, such as new Thread (t), which has not started running. When a thread is in the newly created state, the description program has not yet run the code in the thread.
Can run threads
Once the start () method is called, the thread is in the runnable state, the thread in the running state may or may not be running, which depends on the operating time provided by the OS. In fact, the interruption is to allow other threads to get running time.
Blocked threads and waiting threads
Blocked threads and waiting threads, they are temporarily inactive, do not run any code and consume the least amount of resources. Until the thread scheduler activates it again.
When a thread attempts to acquire an internal object lock that is held by another thread, the thread goes into a blocking state. When all other threads release the lock, and the scheduler allows the thread to hold him, the thread becomes non-blocking.
When a thread waits for another thread to notify the scheduler of a condition, it enters its own wait state. This behavior occurs if you call the Object.wait method or the Thread.Join method, or wait for lock or condition.
Timing Status
There are several methods that have a timeout parameter that calls them causing the thread to enter a timed state, which will continue until the timeout expires or the appropriate notification is received. Methods with timing Thread.Sleep (), object.wait (), Thread.Join (), Lock.trylock (), condition.await
Terminated thread
There are two reasons for a thread termination:
The Run method exits gracefully and dies naturally.
died unexpectedly because an exception was not caught and the Run method was terminated
Thread Manipulation API
Get thread Information
Thread Thread.CurrentThread () method: Gets the thread that is currently running the code snippet
Thread thread = Thread.CurrentThread ();
Boolean isAlive (): Test thread is active
Boolean Isdaemon (): Test whether the thread is a daemon thread
Boolean isinterrupted (): Test thread has been interrupted
Long GetId (): Gets the thread identifier
String getName (): Returns the thread name
int getpriority (): Return thread Priority
Thread.state getState (): Get thread state
Thread Priority
Thread switching is controlled by thread scheduling, and we cannot interfere with code, but we can improve thread priority to maximize the chance of a thread acquiring a time slice.
Thread priority is divided into 10 levels, of 1-10, of which 1 is the smallest and 10 is the largest. Thread provides three constant values representing the lowest, highest, and default precedence
Thread.min_prioriity
Thread.max_priority
Thread.normal_priority
Set by the SetPriority () method
Daemon Threads
Java threads are divided into two categories: the user thread and the daemon thread (the daemon thread). Daemon threads are handy for running other threads, such as the garbage collector is a daemon thread. Daemon and user thread are not different, the main difference is the departure of the virtual machine: When all user thread exit, only daemon Thread is left, then the virtual machine will be exited. The daemon is not the only virtual machine available, and the user can also set the pass: Setdaemon (Boolean on)
Do not easily set the daemon thread, because you do not know when the user thread is finished, if the user thread after the completion of the daemon thread you defined is not finished, it will also be forced to quit
Sleep () method
The sleep (Long mills) method is to cause the current process to block state, enter the blocking time for the specified number of milliseconds, block the time passed into the runable state, and wait for the time slice to be allocated. This method throws a interruptedexception at the time of declaration, so the exception is caught when using this method.
Yield () method
static void Yield (): voluntarily let go of the time slice back to runnable state, waiting to allocate time slices.
Join () method
Used to wait for the current thread to end, the method throws Interruptedexception.
Thread synchronization
Thread concurrency security issues occur when multiple threads read and write to the same critical resource at the same time. For example, when two threads read the same object, and each thread modifies the state of the object, the error occurs, which is called a race condition.
If you want to solve a thread-safety problem, you need to change the asynchronous operation into a synchronous operation:
Asynchronous operations: Multithreading concurrent operations, each performing their own
Synchronous operations: There are sequential operations that you perform I do not perform
Lock Object
Java provides two mechanisms to prevent code blocks from being interfered by concurrent access, one that is familiar with using the Synchronized keyword, and the other using the Reentrantlock class.
Reentrantlock:
Lock lock = new Reentrantlock (), Lock.lock (), try{//critical section code block, which guarantees that only one thread will enter the critical section at any time, and once a thread has blocked the lock object, no other thread can pass the lock statement// When lock is called, they are blocked until the first thread releases the lock object}finally{lock.unlock ();}
Unlock release lock object must be put in finally, if the critical section code throws an exception, finally can release the lock object, otherwise the other threads will always block.
Each such object has its own reentrantlock () object, and if two threads access the same class object, the serial service is provided. However, when accessing different objects, each thread has a different lock object, and two threads do not clog. Operation of different instances, between threads is unaffected.
Condition Object
Consider that when a thread enters the critical section and discovers that a condition is required to run, he has acquired the lock object, but cannot execute it down, which is solved by the conditional object (the condition variable) in Java.
A lock object can have multiple conditional objects and use the await () method to obtain a conditional object using the Newcondition () method, when it is possible for a condition to be executed (which can be judged to determine whether the condition is met), when the current thread is blocked and the lock is discarded. When another thread finishes executing, the Signalall () method is called when the condition is satisfied so that all threads waiting for one condition are activated.
Lock lock = new Reentrantlock (); Condition Condition = Lock.newcondition (); Lock.lock (); try{if (//Determine if a condition is satisfied, if not satisfied) conditon.await (); //Critical block blocks, which ensures that only one thread enters the critical section at any time, Once a thread has blocked the lock object, no other thread can pass the lock statement//When lock is called, they are blocked until the first thread releases the lock object ... After the other threads have finished executing, the current condition may be met, reactivation of condition.signalall (); } Finally{lock.unlock ();}
Using the Synchronized keyword
Declare the method with the Synchronized keyword. An internal lock is provided for each object from Jdk1.0,java, and if a method uses the Synchronized keyword adornment, the object lock will protect the entire method, that is, the thread must obtain an internal lock object to invoke the method. The internal lock object also has a related condition, and the Wait () method adds a thread to the wait set, and the Notify/notofyall method touches the blocking state of the waiting thread.
The wait () method is equivalent to the await () method above, and Notify/notifyall is equivalent to the Signal/signalall method above.
Public synchronized void Method () {if (//Condition State) wait (); .... Notifyall ();}
This method of direct locking is required to lock the current method, there is a synchronous blocking.
Synchronized (Sync Monitor-lock object) { //code block}
Select the appropriate lock object:
Synchronized need to lock an object to ensure thread synchronization, then this object should ensure that when multiple threads need to be synchronized to access the synchronization block, they should see the same lock object, otherwise not achieve the synchronization effect, usually use this as the lock object.
So when do you use the displayed thread lock Lock/unlock, and when to use the Synchronized keyword?
The best case is not to use a mechanism in the java.util.concurrnt package that locks the code you are dealing with. For example, you can use a blocking queue to complete
If you use the Synchronized keyword for your program, use it as much as you can to reduce the amount of code and prevent errors.
Executorservice Implementing a thread pool
Thread pool role: Controlling the number of threads, reusing threads
When a program creates a large number of threads and destroys them at the end of a task, it can cause excessive resource consumption and the risk of switching threads, causing the system to crash and use a thread pool to solve the problem.
Principle: First create some threads, their collections become the thread pool, when the server accepts a request from the client, a free thread is fetched from the thread pool, and the service completes without shutting down the thread and returning to the thread pool. In the online pool programming model, the task is submitted to the thread pool, not to one of the threads, and after the thread pool is taken to the task, there are no idle threads in the inline pools, and the task is given to the idle thread. One thread can perform only one task, but it is possible to submit multiple tasks to the thread pool at the same time.
Implementation method:
1.
Executorservice pool = Executors.newcachedthreadpool ();
Create a thread pool that can create new threads as needed, but reuse them when previously constructed threads are available.
2.
Executorservice pool = Executors.newfixedthreadpool (nthreads);
Create a fixed collection of thread pools that share unbounded queues to run these threads.
3.
Executorservice pool = Executors.newscheduledthreadpool (corepoolsize)
Creates a thread pool that schedules a command to run after a given delay or executes periodically.
4.
Executorservice pool = Executors.newsinglethreadexecutor ();
Create a executor that uses a single work thread to run the thread in an unbounded sequence.
Class Samplethread {public static void main (string[] args) {Executorservice pool = Executors.newfixedthreadpool (2); Handler Handler = new Handler (); for (int i =0; i<5;i++) {Pool.execute (Handler);}}} Class Handler implements runnable{@Overridepublic void Run () {String name = Thread.CurrentThread (). GetName (); for (int i=0 ; i<10;i++) {System.out.println ("Currently executing thread is:" +name), try {thread.sleep (+);} catch (Interruptedexception e) { E.printstacktrace ();}} SYSTEM.OUT.PRINTLN ("Task execution Complete");}}
Blockingqueue
Blockingqueue is a double-buffered sequence, and we can use query if we need to use a queue when multithreading is concurrent. However, synchronization slows down concurrent operations on query, and you can use Blockingquery.
The Blockingqueue uses two queues internally, allowing two two threads to be stored at the same time in the queue, one for read operations. Improves queue access efficiency while ensuring concurrency security
When Blockingqueue is empty, the thread will be interrupted to wait until Blockingqueue has something, and the thread will be woken up to continue the operation. If the Blockingqueue queue is full and then put something inside, the thread will be interrupted into a wait state until there is room in the blockingqueue until it wakes up and continues.
|
Throw exception |
Special values |
Blocking |
Timeout |
| Insert |
Add (E) |
Offer (e) |
Put (e) |
Offer (E,time,unit) |
| Removed from |
Remove () |
Poll () |
Take () |
Poll (Time,unit) |
| Check |
Element () |
Peek () |
Not available |
Not available |
Add (E): Adds an element to the queue, returns True if Blockingqueue can accommodate, or throws an exception
Offer (E): Adds an element to the queue, returns True if Blockingqueue can hold, otherwise returns false
Put (E): Add an element to the queue, insert if blockingqueue can accommodate, or enter a blocking state if it cannot be inserted until it can be inserted
The following method is the same principle
Four implementation classes for Blockingqueue
Arrayblockingqueue: Specifies the size of the blockingqueue, you need to specify an int parameter to specify its size, containing the objects are in FIFO order.
Linkedblockingqueue: Blockingqueue of variable size, if the constructor specifies a size, it is the blockingqueue queue size, or Integer.max_value size if not specified. The contained objects are sorted in FIFO order.
Priorityblockingqueue: Similar to Linkedblockqueue, but not ordered in FIFO order. Instead, the order in which the comparator is determined depends on the natural order of the object or the constructor.
Synchronousblockingqueue: is a special kind of blockingqueue, the operation needs to be executed alternately.
which Linkedblockingqueue and the Arrayblockingqueue compare them , the data structures behind them are different. , cause Linkedblockingqueue the data throughput to be greater than Arrayblockingqueue, However, when the number of threads is large, its performance is less predictable than Arrayblockingqueue.
Viewing its source code will discover that each operation of the queue is reentrantlock with a lock object.
Test the Offer method if inserting more than two seconds without entering the sequence returns false
blockingqueue<integer> queue = new arrayblockingqueue<integer>, for (int i =0;i<20;i++) {try {Boolean result = Queue.offer (i, 2, timeunit.seconds);//Insert after 2 seconds if not successfully returned FALSESYSTEM.OUT.PRINTLN ("Deposit succeeded:" + result);} catch (Interruptedexception e) {e.printstacktrace ();}}
Test the poll () method and return False if the element is not removed for more than 2 seconds
blockingqueue<integer> queue = new arrayblockingqueue<integer>, for (int i =0;i<10;i++) {Queue.offer (i);} for (int i=0;i<20;i++) {try {Integer result = Queue.poll (2, timeunit.seconds); If the element is not taken after two seconds, the NULLSYSTEM.OUT.PRINTLN is returned ("Result:" +result);} catch (Interruptedexception e) {e.printstacktrace ();}}
Copyright NOTICE: This article for Bo Master original article, without Bo Master permission not reproduced.
Java Multi-Threading