1, Threads and processes
- Thread is the smallest execution unit of a program.
- Process is a basic unit of resource allocation and scheduling in operating system.
- A program has at least one process, and a process contains at least one thread. When the program runs, even if it does not create a thread, there will be multiple threads in the background. Such as GC thread, main thread, etc. The main thread is called the main thread, which is the entry point of the system and is used to execute the whole program.
- The execution of multiple threads is scheduled by the operating system, and the execution order can not be interfered by human beings. The operating system allocates CPU time slices for threads and competes among threads.
- Each thread has its own working memory, but improper control of loading and storage main memory (shared memory) will cause data inconsistency. Therefore, concurrency control needs to be added when operating on the same shared resource.
- The purpose of introducing thread is to make full use of CPU resources so that it can process multiple tasks in parallel, reduce time consumption and improve efficiency. However, threads will bring additional overhead, such as thread creation and destruction time, CPU scheduling time, concurrency control overhead. Therefore, the more threads are created, the better. Therefore, thread pool is introduced to better control resources.
- Multithreading is not necessarily fast. Affected by other factors such as hardware and network, for example, the network bandwidth is 2m, the download speed is 1m/s, and starting 10 threads will not reach 10m/s.
Case: multi thread downloading pictures
public class TDownLoader extends Thread { private String url; private String name; public TDownLoader(String url, String name) { this.url = url; this.name = name; } @Override public void run() { WebDownLoader downLoader = new WebDownLoader(); downLoader.downLoad(url, name); System.out.println(name); } public static void main(String[] args) { TDownLoader t1=new TDownLoader("https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1606411566549&di=9dfa479ec43c80d34ea4a84fc2c3f866&imgtype=0&src=http%3A%2F%2Fgss0.baidu.com%2F94o3dSag_xI4khGko9WTAnF6hhy%2Fzhidao%2Fpic%2Fitem%2F14ce36d3d539b6002ac5706de850352ac75cb7e4.jpg","C:\\Users\\Administrator\\Desktop\\ttt\\t1.jpg"); TDownLoader t2=new TDownLoader("https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1606411566548&di=f901ee991c205196f80ca1f03508d31b&imgtype=0&src=http%3A%2F%2Fpic1.win4000.com%2Fpic%2F6%2Fa6%2F39b2375640.jpg","C:\\Users\\Administrator\\Desktop\\ttt\\t2.jpg"); TDownLoader t3=new TDownLoader("https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1606411566547&di=a3caf55c682e66b095a4f0990ea3c0f7&imgtype=0&src=http%3A%2F%2Fpic1.win4000.com%2Fpic%2F8%2F09%2Fa615556832.jpg","C:\\Users\\Administrator\\Desktop\\ttt\\t3.jpg"); t1.start(); t2.start(); t3.start(); } }
2, Classification of threads
Threads are divided into user threads and daemon threads:
User Thread: it is generally a thread created in a program
Daemon Thread: a Thread that serves user threads. It will terminate only when all user threads end, such as GC threads. Turn a user Thread into a daemon Thread through the setDaemon(true) method of Thread.
3, Thread creation
There are four main ways to create threads:
1. Inherit Thread class
2. Implement Runnable interface
3. Implement the Callable interface, which can have a return value, which needs to be used in combination with FutureTask
4. Perform task execution through thread pool
Method 1: inherit Thread class
Declare a subclass of Thread class, which overrides the run method. When using, you must create an instance of this subclass and call the start() method to start the Thread
package com.whw.thread.generic; /** * @description Thread creation: inherit thread class */ public class MyThread01 extends Thread { @Override public void run() { System.out.println("I am MyThread01"); } }
Method 2: implement Runnable interface
Declare a class that implements the Runnable interface, and this class implements the run method. When using, you must create a new Thread class, and then create an instance of this subclass as a parameter of the Thread class. Call the start() method of the Thread class from new
package com.whw.thread.generic; /** * @description Thread creation: implement Runnable interface */ public class MyThread02 implements Runnable{ @Override public void run() { System.out.println("I am MyThread02"); } }
Using the: start() method to start a thread does not immediately execute the thread run method. The specific time needs cpu scheduling, and human intervention is not allowed
public class TestThread { public static void main(String[] args) { //Create a Thread by inheriting the Thread class, directly create a subclass instance, and call the start() method to start the Thread MyThread01 myThread01=new MyThread01(); myThread01.start(); //To create a Thread by implementing the Runnable interface, first create a subclass instance, and then a Thread class, //Call the subclass instance as a parameter and call the start() method to start the thread. MyThread02 myThread02=new MyThread02(); new Thread(myThread02).start(); } }
Note: if you call the run() method directly, it will be executed as a normal method and will still be called in a single thread sequence.
Mode 3: implement Callable interface
class Thread3 implements Callable<Integer> { @Override public Integer call() throws Exception { System.out.println("Thread starts execution..."); int i = 10 / 2; System.out.println("results of enforcement i=: " + i); System.out.println("End of thread execution..."); return i; } }
The thread that calls the Callbale interface
public static void main(String[] args) throws ExecutionException, InterruptedException { FutureTask<Integer> futureTask = new FutureTask<Integer>(new Thread3()); new Thread(futureTask).start(); Integer i = futureTask.get();// Get return value System.out.println(i); }
Mode 4: use thread pool
public static void main(String[] args) { // Create thread pool ExecutorService executorService = Executors.newFixedThreadPool(5); executorService.execute(new Thread1()); }
Comparison of four methods:
1 can only inherit single, 2 and 3 can inherit multiple, with better scalability
1. The method implemented by 2 is run(), and the method implemented by 3 is call()
1. 2 can't get the return value and throw exceptions; 3 can get the return value and throw exceptions
1. 2 and 3 cannot control resources, 4 can directly control resources, and the performance is stable
4, Simplified way of thread creation
1. Regular use
package com.whw.thread.generic; public class NormalThread implements Runnable { @Override public void run() { for (int i = 0; i < 20; i++) { System.out.println("I am MyThread01---" + i); } } public static void main(String[] args) { new Thread(new NormalThread()).start(); } }
2. Using static inner classes
package com.whw.thread.generic; public class TestThread { // Define static inner classes static class Test implements Runnable { @Override public void run() { for (int i = 0; i < 20; i++) { System.out.println("I am MyThread01---" + i); } } } public static void main(String[] args) { // Using static inner classes new Thread(new Test()).start(); } }
3. Use local inner classes
package com.whw.thread.generic;
public class TestThread {
public static void main(String[] args) {
// Define local inner classes
class Test implements Runnable {
@Override
public void run() {
for (int i = 0; i < 20; i++) {
System.out.println("I am MyThread01---" + i);
}
}
}
// Use local inner classes
new Thread(new Test()).start();
}
}
package com.whw.thread.generic; public class TestThread { public static void main(String[] args) { // Define local inner classes class Test implements Runnable { @Override public void run() { for (int i = 0; i < 20; i++) { System.out.println("I am MyThread01---" + i); } } } // Use local inner classes new Thread(new Test()).start(); } }
4. Use anonymous inner classes
package com.whw.thread.generic;
public class TestThread {
public static void main(String[] args) {
// Use anonymous inner classes: you must use interfaces or parent classes
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 20; i++) {
System.out.println("I am MyThread01---" + i);
}
}
}).start();
}
}
package com.whw.thread.generic; public class TestThread { public static void main(String[] args) { // Use anonymous inner classes: you must use interfaces or parent classes new Thread(new Runnable() { @Override public void run() { for (int i = 0; i < 20; i++) { System.out.println("I am MyThread01---" + i); } } }).start(); } }
5. jdk8, using Lambda expressions
package com.whw.thread.generic; public class TestThread { public static void main(String[] args) { // Using Lambda expressions new Thread(() -> { for (int i = 0; i < 20; i++) { System.out.println("I am MyThread01---" + i); } }).start(); new Thread(() -> { for (int j = 0; j < 20; j++) { System.out.println("I am MyThread02---" + j); } }).start(); } }
lambda expressions are based on:
package com.whw.thread.generic; class Love { public static void main(String[] args) { //This code is equivalent to creating an ILove implementation class, and the method body in {} rewrites the method for the implementation class /*ILove love = (String name) -> { System.out.println("I Love -->" + name); };*/ //When a parameter is, the parameter type may not be written /*ILove love = (name) -> { System.out.println("I Love -->" + name); };*/ //You can use a parameter without writing parentheses /*ILove love = name -> { System.out.println("I Love -->" + name); };*/ //When a parameter has only one line of content in the method body, you don't need to write {}, but it should be written in one line //ILove love = name -> System.out.println("I Love -->" + name); //love.lambda("Wang Wei"); //Interface has two parameters with return value IInterest interest = (a, b) -> { return a + b; }; Integer result = interest.lambda(1, 2); System.out.println(result); } } interface ILove { void lambda(String name); } interface IInterest { Integer lambda(Integer a, Integer b); }
5, Common methods of thread
1,currentThread()
Gets the thread currently being called
2,getId()
Gets the unique id number of the thread
3,getName()
Gets the name of the thread
4,getState()
Gets the status of the thread
5,isDaemon()
Determine whether it is a daemon thread
6,setDaemon(boolean on)
Set as a daemon thread. It can only be set as a background thread before the thread starts
7,isAlive()
Determines whether the current thread is active
8,activeCount()
Determine the number of threads surviving in the current thread group
9,getThreadGroup()
Gets the thread group of the current thread
10,sleep(long)
Let the thread sleep for the specified number of milliseconds. Resources are not released during sleep
11. Stop thread
stop(): abandoned
interrupt():
It does not terminate the running thread. You need to add a judgment to stop the thread
Determine whether the thread is interrupted. this.isInterrupted()
run(): end of run
Exception method to stop thread:
public class StopThread { public static void main(String[] args) { MyThread myThread = new MyThread(); myThread.start(); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } // Stop thread myThread.interrupt(); } } class MyThread extends Thread { @Override public void run() { try { for (int i = 0; i < 1000000; i++) { System.out.println(i); if (this.isInterrupted()) { System.out.println("I was terminated"); // Throw an exception to interrupt the execution of the following code in the for loop throw new InterruptedException(); } } System.out.println("I am output, indicating that the thread has not stopped"); } catch (InterruptedException e) { System.out.println("The exception method ends the execution of the thread"); e.printStackTrace(); } } }
Tagging to stop a thread:
package com.whw.thread.state; /** * @description Terminate thread * 1,Number of times the thread has completed normal execution -- > * 2,External interference -- > Add identification * Do not use the stop, destroy method */ public class TerminateThread implements Runnable { //1. Add an identifier to mark whether the thread body can run private boolean flag = true; private String name; public TerminateThread(String name) { this.name = name; } @Override public void run() { int i = 0; //2. Association ID, true -- > run, false -- > stop while (flag) { System.out.println(name + "-->" + i++); } } //3. Identification of method change provided externally public void terminate() { this.flag = false; } public static void main(String[] args) throws InterruptedException { TerminateThread tt = new TerminateThread("A"); new Thread(tt).start(); for (int i = 0; i <= 99; i++) { if (i == 88) { tt.terminate();//Thread termination, deadlock resolution System.out.println("tt game over"); } System.out.println("main-->" + i); } } }
12. Pause and resume threads
suspend(): deprecated. Improper use may cause exclusive lock and data out of sync
resume(): it has been discarded. Improper use may cause exclusive lock and data out of sync
13,yield()
Thread comity does not necessarily succeed every time. It just makes the current thread give up the contention for CPU resources. It may get CPU resources immediately after giving up
14,setPriority()
Set the priority of threads. The default is 5,1 ~ 10 levels, which helps the thread planner to allocate resources to threads with high priority as much as possible
With inheritance
High priority may not be executed first every time
15,join(long millis)
join merge thread and queue thread. After this thread is completed, other threads will be executed, and other threads will be blocked. He is a member of the method