runnable create thread
Running a task in a single thread requires three steps:
1. You need a class that implements the Runnable interface and put the code to be executed by this task into the run method of this class.
public class multithread implements Runnable{ public static void main(String[] args) { multithread m = new multithread(); Thread thread = new Thread(m); thread.start(); } @Override public void run() { System.out.println(123); } }
Because Runnable is a functional interface, you can use a lambda expression instead of implementing this interface.
public class multithread{ public static void main(String[] args) { Runnable r = () -> { System.out.println(123); }; Thread t = new Thread(r); t.start(); } }
2. Construct Thread object from Runnable.
3. Start the thread.
Let two threads run at the same time:
public class multithread{ public static void main(String[] args) { Runnable r1 = () -> { for (int i = 0; i < 5; i++) { System.out.println("thread 1: " + i); } }; Runnable r2 = () -> { for (int i = 0; i < 5; i++) { System.out.println("thread 2: " + i); } }; new Thread(r1).start(); new Thread(r2).start(); } }
The results appear alternately, indicating that it is indeed running concurrently.
thread 1: 0 thread 1: 1 thread 1: 2 thread 1: 3 thread 2: 0 thread 2: 1 thread 2: 2 thread 2: 3 thread 2: 4 thread 1: 4
Inherit thread to create thread
This is an outdated creation method, because this method binds the tasks to be executed with the parallel running mechanism, and the two should be decoupled.
class MyThread extends Thread{ public void run(){ // task } }
Call the run method of thread or runnable
public class multithread{ public static void main(String[] args) { Runnable r1 = () -> { for (int i = 0; i < 5; i++) { System.out.println("thread 1: " + i); } }; Runnable r2 = () -> { for (int i = 0; i < 5; i++) { System.out.println("thread 2: " + i); } }; r1.run(); new Thread(r1).start(); new Thread(r2).start(); } }
This will not create a new thread to execute the task, or execute it in the original thread.
thread 1: 0 thread 1: 1 thread 1: 2 thread 1: 3 thread 1: 4 // The following parallel operations can only be executed after the run of r1 is executed in the main thread thread 1: 0 thread 2: 0 thread 2: 1 thread 2: 2 thread 2: 3 thread 2: 4 thread 1: 1 thread 1: 2 thread 1: 3 thread 1: 4
Thread state
Six states:
- New
- Runnable
- Blocked
- Waiting
- Timed waiting
- Terminated
Each state is described in detail below.
newly build
After new Thread(r), the thread is in the new state and does not start running.
Operable
After calling the start() method, the thread becomes runnable, but not necessarily running. The operating system generally uses preemptive scheduling, which gives each thread a certain time slice to execute according to the priority, and deprives the running right after the time slice is used up.
Blocking and waiting
At this time, the thread is inactive, that is, it does not run code and needs to be rescheduled for activation. The following are several reasons why threads enter blocking or waiting:
- When a thread attempts to acquire a lock held by another thread, the thread will be blocked until the other threads have released the lock and the thread scheduler allows the thread to hold the lock.
- When condition
- Calling some methods with timeout parameters will make the thread enter timing waiting, such as Thread.sleep, Object.wait, Thread.join
When a thread is reactivated, the scheduler checks its priority and schedules it to run.
Terminate thread
The thread terminates naturally after completing the run method, or unexpectedly due to an uncapped exception. In the past, some methods can pause or terminate threads, such as stop, suspend and resume, but these methods have been abandoned.
Thread properties
Interrupt thread
In addition to the methods that have been abandoned, Java cannot forcibly terminate a process, but it can use interrupt and exception mechanisms to terminate.
Calling interrupt on a thread object will set the interrupt state of the thread, and each thread will check this state from time to time
thread.interrupt();
When a thread is blocked, it cannot check the interrupt status. Java introduces an InterruptedException exception. When the interrupt method is called on a thread blocked by calling sleep or wait, the blocked call will be interrupted by the exception. The interrupted thread can handle exceptions by itself, such as continuing execution or terminating the thread.
Runnable r = () -> { try{ // task } catch(InterruptedException e){ // thread is interrupted during sleep or wait } finally{ // clean up, if require } };
If there is Thread.sleep() in the code executed by the thread, you must use try catch to catch the InterruptedException exception or throw the exception to the run method. The reason is that these blocking calls will be interrupted by exceptions, so we need to deal with them in the code.
Daemon thread
Daemon threads provide services to other threads, such as timer threads and threads that empty expired cache entries. When only the daemon thread is left in the process, the virtual machine will exit. Calling setDaemon(true) before threads start can turn threads into daemon threads.
Thread name
During thread dump, the name of the thread may be useful and can be set with setName("name").
thread priority
By default, a thread will inherit the priority of the thread that constructs it. You can use setPriority to set the thread priority, the minimum Thread.MIN_PRIORITY is 1 and the maximum is 10. However, this priority depends on the implementation of the system, so it is not necessarily effective in practice.