The difference between throw and throws
Throw, acting inside the method, is used to actively throw exceptions
throws, which acts on the method declaration. Declaring the method may throw some exceptions
For the exception handling method in the project, we generally throw it up layer by layer, and finally handle it uniformly through the exception handling mechanism (display the exception page or return the unified json information). Custom exceptions generally inherit RunntimeException. Let's take a look at Hibernate and other frameworks. Their exception system is finally inherited from RunntimeException
How threads are created
We often say it in the following three ways:
inherit Thread realization Runable Interface realization Callable Interface (you can get the return value after thread execution)
However, in the latter two cases, a more accurate understanding is to create an executable task, which should be executed in a multi-threaded manner,
It also needs to be executed by creating a Thread object, such as new Thread (New runnable() {}) start(); In this way.
In actual development, we usually use Thread pool to complete the creation of Thread and better manage Thread resources.
Case: how to start the thread correctly
class MyThread extends Thread{ @Override public void run() { System.out.println(Thread.currentThread().getName()+": running....."); }
}
public static void main(String[] args){ MyThread thread = new MyThread(); //How to start the thread correctly //thread.run();// Calling a method does not open a new thread thread.start();
}
Case: implementing runnable only creates an executable task, not a thread
class MyTask implements Runnable{
@Override public void run() { System.out.println(Thread.currentThread().getName()+":running...."); }
}
public static void main(String[] args){ MyTask task = new MyTask(); //task.start(); // It cannot be started directly as a thread //It expresses a task that needs to start a thread to execute new Thread(task).start(); }
Case 3: runnable vs callable
class MyTask2 implements Callable{
@Override public Boolean call() throws Exception { return null; }
}
To be clear:
In essence, the way to create a Thread is to inherit the Thread, which is the Thread pool. The internal Thread object is also created to execute the task
Is the execution of an ordinary main method in single thread mode or multi thread mode? Why?
Because java has an important feature called automatic garbage collection mechanism, the answer is multithreading. There are two parts: main thread (user thread) and garbage collection thread GC (guard thread).
What is deadlock
Deadlock, philosopher's problem.
The scenario of switching to thread is that thread a holds exclusive lock resource a and attempts to obtain exclusive lock resource b
Meanwhile, thread B holds exclusive lock resource B and attempts to acquire exclusive lock resource a
In this way, thread A and thread B hold the lock required by each other, resulting in blocking and eventually deadlock.
public class Deadlock {
private static final Object a = new Object(); private static final Object b = new Object(); public static void main(String[] args){ new Thread(new Task(true)).start(); new Thread(new Task(false)).start(); } static class Task implements Runnable{ private boolean flag; public Task(boolean flag){ this.flag = flag; } @Override public void run() { if(flag){ synchronized (a){ System.out.println(Thread.currentThread().getName()+"->Get a resources"); synchronized (b){ System.out.println(Thread.currentThread().getName()+"->Get b resources"); } } }else{ synchronized (b){ System.out.println(Thread.currentThread().getName()+"->Get b resources"); synchronized (a){ System.out.println(Thread.currentThread().getName()+"->Get a resources"); } } } } } } //There may be deadlock. If the first thread has finished and the second thread obtains the execution permission, there will be no deadlock
2. How to prevent deadlock? (key points)
Reduce synchronous code block nesting
Reduce the use granularity of locks, and do not share a lock for several functions
Try to use the method of tryLock (timeout) as much as possible. You can set the timeout time, so that after the timeout, you can actively exit to prevent deadlock (key)
Four conditions satisfied by deadlock
Mutually exclusive, inalienable, cyclic waiting, request and hold
Necessary conditions for deadlock generation:
Mutually exclusive condition: the process requires exclusive control of the allocated resources, that is, a resource is occupied by only one process in a period of time.
Request and hold condition: when the process is blocked due to the request for resources, keep the obtained resources.
Conditions of non deprivation: the resources obtained by the process cannot be deprived before they are used up, and can only be released by themselves when they are used up.
Loop waiting condition: when a deadlock occurs, there must be a loop chain of process resources.
The difference between Sleep and wait
1. Different categories:
sleep Method is defined in Thread upper wait Method is defined in Object upper
2. The processing methods of lock resources are different
sleep The lock will not be released wait The lock will be released
3. Scope of application:
sleep Can be used in any code block wait Must be executed in a synchronization method or synchronization code block
4. Methods used together with wait
void notify() Wakes up a single thread that is waiting on this object's monitor. Wake up a single thread waiting on this object monitor void notifyAll() Wakes up all threads that are waiting on this object's monitor. Wake up all threads waiting on this object monitor void wait( ) Causes the current thread to wait until another thread invokes the notify() method or the notifyAll( ) method for this object. Causes the current thread to wait until another thread calls this object notify( ) Method or notifyAll( ) method
life cycle
1. When a thread calls wait() or join, the thread will enter the waiting state. When notify or notifyAll is called, or after the execution of the join thread is completed, the thread will enter the runnable state
2. When the thread calls sleep(time) or wait(time), it enters the timed waiting state,
Finally, leave a question to think about. Why should wait be defined in Object instead of Thread?
To explain, let's recall that in the synchronous code block, we said that we need an object lock to achieve the mutual exclusion effect of multithreading, that is, the Java lock is object level, not thread level.
Why must wait be written in a synchronized code block?
The reason is to prevent the CPU from switching to other threads, and other threads execute the notify method in advance, which can not meet our expectations (wait first and then wake up by other threads), so we need a synchronization lock to protect it
What are the thread pools provided by JDK? How should we use the actual development?
1. JDK represents the thread pool through the interface ExecutorService, and creates a variety of thread pool objects through the tool class Executors
2. The characteristics of various thread pools are as follows:
newSingleThreadExecutor Create a singleton thread pool, which will only use a unique worker thread to execute tasks, ensuring that all tasks are in the specified order(FIFO, LIFO, priority)Execution. newFixedThreadPool Create a fixed length thread pool to control the maximum concurrent number of threads. The exceeded threads will wait in the queue. newCachedThreadPool Create a cacheable thread pool. If the length of the thread pool exceeds the processing needs, you can flexibly recycle idle threads. If there is no recyclable thread, you can create a new thread. newScheduledThreadPool Create a fixed length routing pool to support regular and periodic task execution.
3. How do we use it in actual development? (key points)
In actual development, thread resources must be provided through thread pool, and it is not allowed to create threads explicitly in the application
The advantage of using thread pool is to reduce the time spent on creating and destroying threads and the overhead of system resources, and solve the problem of insufficient resources. If the thread pool is not used, it may cause the system to create a large number of similar threads, resulting in memory consumption or "excessive switching"
In actual development, thread pools are not allowed to be created using Executors, but through ThreadPoolExecutor
FixedThreadPool and SingleThreadPool,The allowed request queue length is Integer.MAX_VALUE,A large number of requests may accumulate, resulting in OOM. CachedThreadPool and ScheduledThreadPool,The number of creation threads allowed is Integer.MAX_VALUE,A large number of threads may be created, resulting in OOM
Therefore, to sum up, we will all use the underlying method to create thread pools. You can see from the source code of various thread pools that they are created by the same class