Three. Multi-threading
- Thread creation
way1Inheriting the Thread step:A: Custom MyThread inherits Thread class.BOverride run() in the :MyThread class: not all code in the class needs to be executed by the thread. To distinguish which code can be executed by threads, Java provides run() in the Thread class to contain code that can be executed by threads.CCreate an objectD: Starts the thread in start () mode2Implementing the Runnable interface Steps:A: Custom class MyRunnable implements the Runnable interfaceB: Overrides the run() methodC: Creates an object of the MyRunnable classD: Creates an object of the Thread class and passes the object of the C step as a construction parameter3: Implements the Callable<T> interface, where T indicates the return type. Must be used in conjunction with thread pools.Copy the code
- Which method is more common? Implementing the interface is better because:
-
- Java does not support multiple inheritance, so if you inherit Thread, you cannot inherit other classes, but you can implement multiple interfaces.
-
- It is convenient for the same object to be used by multiple threads
-
- The class might just need to be executable, and inheriting the entire Thread class would be too expensive.
- Why use start () to start a thread
- The start() method is called to start a thread and put it into a ready state; executing the run() method directly does not execute in multithreaded fashion.
- Run (): simply encapsulates code that is being executed by a thread. Direct calls are normal methods; Start (): The thread is started, and the JVM calls its run() method.
- Synchronized keyword: addresses the synchronization of access to resources between multiple threads, ensuring that the method or code block modified by it can only be executed by one thread at any time. 4 ways to use :(unreadable)
1 synchronized(this) : When thread A executes the statement, the object of the statement is locked, and other threads cannot access all objects in the objectsynchronizedCode block.2 synchronized(obj) : Lock object obj, other threads on all in objsynchronizedAccess to the code block is blocked.3 synchronized method(a): Similar to (1), except that (1) the lock is acquired when the thread executes the statement in a method, whereas locking a method is acquired immediately when the method is called. 4synchronized static method(a): When a thread executes into the statement, the lock is acquired, and all other threads that called the method block, but the rest of the class does notstaticDeclared methods can be accessed even if those methods are usedsynchronizedDeclarative, butstaticDeclared methods are blocked; Note that this lock is independent of the object.Copy the code
- The difference between Synchronized and Lock
- Synchronized is a built-in Java keyword and Lock is a Java class at the JVM level.
- Synchronized cannot determine whether a Lock is obtained. Lock can determine whether a Lock is obtained and can actively attempt to obtain the Lock.
- Synchronized automatically releases the lock (a thread releases the lock after executing the synchronization code; The Lock must be released manually in finally (unlock()). Otherwise, the thread is likely to deadlock.
- Two threads 1 and 2 that use the synchronized keyword, if the current thread 1 acquires the lock, thread 2 waits. If thread 1 is blocked, thread 2 will wait forever, while a Lock Lock will not necessarily wait. If an attempt to acquire the Lock fails, the thread can terminate without waiting forever.
- Synchronized locks are reentrant, uninterruptible, and non-fair, while Lock locks are reentrant, judge, and fair (both)
- Lock locks are suitable for synchronization problems with a lot of synchronized code, and synchronized locks are suitable for synchronization problems with a small amount of synchronized code.
- The realization principle of synchronized
-
- The JVM implements method synchronization and code block synchronization based on entering and exiting Monitor objects.
-
- Method-level synchronization: The JVM uses the ACC_SYNCHRONIZED access flag to distinguish a method from a synchronized method. If this access flag is set, the thread of execution holds Monitor, then executes the method, and finally releases Monitor when the method completes, either normally or abnormally.
-
- Synchronization of code blocks: Use the bytecode instructions monitorenter and Monitorexit. They are at the beginning and end of the synchronized code block, respectively. When the JVM executes the Monitorenter instruction, the current thread attempts to acquire ownership of the Monitor object, incrementing the lock counter by 1 if it is unlocked or already held by the current thread. When monitorexit is executed, lock counter -1; When the lock counter is 0, the lock is released. If the monitor object fails to be acquired, the thread blocks until another thread releases the lock.
- Lock escalation
- There are four lock states, in descending order: no lock state, biased lock state, lightweight lock state, and heavyweight lock state. Locks can be upgraded but not degraded.
- Why have thread pools:
- Reduce the number of threads created and destroyed, and each worker thread can be reused to perform multiple tasks.
- The number of worker threads in the thread pool can be adjusted according to the capacity of the system, and the server can be exhausted by consuming too much memory.
- Analysis of the important parameters of the ThreadPoolExecutor constructor
- CorePoolSize: Specifies the number of threads in the thread pool
- MaximumPoolSize: Specifies the maximum number of threads in the thread pool
- KeepAliveTime: The idle time allowed by the thread pool to maintain threads
- Unit: keepAliveTime unit.
- WorkQueue: Queue of tasks that have been submitted but not yet executed.
- ThreadFactory: a threadFactory used to create threads, usually using the default.
- Handler: rejects the policy. How to say no to tasks when there are too many to handle.
ThreadPoolExecutor thpool = new ThreadPoolExecutor(corePoolSize,maximumPoolSize,...)
Copy the code
- Thread pool execution flow
- If the number of running threads is less than corePoolSize, create a thread to run the task immediately
- If the number of running threads is greater than or equal to corePoolSize, the task is queued
- If the queue is full and the number of running threads is smaller than maximumPoolSize, create a non-core thread to run the task immediately
- If the queue is full and the number of running threads is greater than or equal to maximumPoolSize, the thread pool throws RejectExecutionException
- The difference between sleep() and wait() methods
- Sleep (): time must be specified; It does not release the lock. sleep(long millis)
- Wait (): specifies either no time or time. It releases the lock.
What is the difference between submit() and execute()
- The submit() method is used to submit tasks that require a return value. The thread pool returns an object of type Future to determine whether the task was successfully executed
- The execute() method is used to submit tasks that do not require a return value, so there is no way to determine whether the task was successfully executed by the thread pool
- ThreadLocal
- The ThreadLocal class allows each thread to bind its own values. The ThreadLocal class can be likened to a box for storing data that is private to each thread.
- volatile
- Once a shared variable (a member variable of a class, a static member variable of a class) is volatile, there are two levels of semantics:
- 1) It ensures visibility when different threads operate on the variable, i.e. one thread changes the value of a variable and the new value is immediately visible to other threads.
- 2) Forbid instruction reordering.