0x00 preface and mind map
1. What is a process? What's up?
We can understand that a qq is equivalent to a process. If you chat with several people at the same time, each chat box is equivalent to a thread (thread is each execution scenario / execution unit of the process)
2. For java?
Start the JVM virtual machine, and then call a main() method. At the same time, it will also call a garbage collection thread to take care of and collect garbage. At least now java has two concurrent threads.
3. The relationship between processes and threads.
(1) Memory is independent and not shared between process (A) and process (B)
(2) Under the same process, the heap memory and method area of thread (A) and thread (B) are shared.
(3) But the stack memory is independent of one thread and one stack
0x01 basic use of thread
0x1 reconstruct the run method and inherit the Runnable interface
Method 1: reconstruction method
Using your own class to inherit the Thread class and rewrite the run method is flawed. When you have more than one Thread and need many threads, you need to overload the run method when using this method
public class JAVA_Threads extends Thread { @Override public void run() { for (int i = 0; i < 1000; i++) { System.out.println("I'm a child thread"+i); } } public static void main(String[] args) { JAVA_Threads threads=new JAVA_Threads(); threads.start(); for (int i = 0; i < 100; i++) { System.out.println("I'm the main thread"+i); } } }
Method 2: inherit Runnable and implement run method
1. Inherit the interface to implement the class methods in the interface and interface oriented programming, which is in line with the thinking of object-oriented programming.
2. After inheriting the interface, you can also inherit other classes to enhance the variability of the code.
class Threads_Test2{ public static void main(String[] args) { Thread thread1=new Thread(new My_thread_run()); Thread thread2=new Thread(new My_thread_run2()); thread1.start(); thread2.start(); } } class My_thread_run implements Runnable{ @Override public void run() { for (int i = 0; i < 100; i++) { System.out.println("This is a child thread"+i); } } } class My_thread_run2 implements Runnable{ @Override public void run() { for (int i = 0; i < 100; i++) { System.out.println("I am a child thread 2"+i); } } }
Method 3: anonymous inner class construction
public static void main(String[] args) { Runnable r = new Runnable() { @Override public void run() { System.out.println("I'm a child thread"); } }; new Thread(r).start(); System.out.println("I'm the main thread"); }
Method 4: implementation of Callable interface
1. In this way, the result returned by the thread can be obtained;
class CallableTest { public static void main(String[] args) throws Exception { MyThread mt = new MyThread(); FutureTask<Integer> result = new FutureTask<Integer>(mt); new Thread(result).start(); // Obtaining the operation result is a synchronization process, that is, the result can be obtained only after the call method is executed Integer sum = result.get(); System.out.println(sum); } } class MyThread implements Callable<Integer> { @Override public Integer call() throws Exception { int sum = 0; for (int i = 1; i <= 100; i++) { System.out.println("I'm doing it"); } return sum; } }
0x2 get some other methods
1. Set and get the name of the thread
a. Process object getName(); public final String getName()
b. Process object setName(); public final synchronized void setName(String name)
2. Get the name of the current process
a.public static native Thread currentThread();
b. The returned object is a thread. Use the thread of this thread getName
class Mythread_Testo2{ public static void main(String[] args) { Thread thread=new Thread(new My_thread_run2()); System.out.println(thread.getName()); thread.setName("I'm your child thread"); System.out.println(thread.getName()); Thread hell= Thread.currentThread(); System.out.println(hell.getName()); } }
0x03sleep() method
1. Look at the source code public static native void sleep (long miles)
a. This method is a static method. Use the class name directly Method call.
b. Where it appears, there is sleep. When it appears in main, it is main sleep.
class Mythread_Test3{ public static void main(String[] args) { Thread thread=new Thread(new My_thread_run2()); thread.start(); try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("Execution complete"); } }
2. Stop sleeping
a.public void interrupt()
b. After using this method, an error will appear, that is, the instruction of cath Block Prints error information
java.lang.InterruptedException: sleep interrupted at java.base/java.lang.Thread.sleep(Native Method) at com.zhonglin.www.My_thread_run2.run(JAVA_Threads.java:44) at java.base/java.lang.Thread.run(Thread.java:833) //Sleep interrupted error message
class Mythread_Test3{ public static void main(String[] args) { Thread thread=new Thread(new My_thread_run2()); thread.start(); try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } thread.interrupt(); System.out.println("Execution complete"); } }
0x4join() method
1.public final void join()
2. The thread will be merged (inserted) into the current thread, blocking the current thread, and the current thread will not continue until the insertion thread is completed.
class Mythread_Test3{ public static void main(String[] args) { Thread thread=new Thread(new My_thread_run2()); System.out.println("I'm executing"); try { thread.join(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("Execution complete"); } }
0x03 thread safe
1. The simplest example is that when you blow up a weak password in a handwritten script, multithreading will significantly improve your efficiency. When you traverse the dictionary, a situation will occur. The first thread reads the first line. If there is no thread safety, your second thread may still be the first line of the readlin dictionary.
2. Asynchronous = concurrent, synchronous = queued
0x1 synchronized code block
1. Synchronized(), the common object in the middle of this bracket must be the one you want to queue up for execution. For example, if you want to withdraw money, one is thread 1 at ATM and the other is thread 2 at bank counter, then their common object is the bank account
2. Working mechanism: when each thread runs to the front of synchronized, it will compare the object to see whether it is a shared object. If it is the same object, it will obtain the lock. If the next thread finds that it is also a shared object, it will wait for the release of the lock and obtain the lock.
public static class sunchironize_teset implements Runnable{ private int num = 100; private boolean flag = true; Object obj = new Object(); @Override public void run() { while (flag){ synchronized (obj){ if (num==0){ flag = false; }else { try { Thread.sleep(50); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("I'm a child thread"+Thread.currentThread()+"numerical value"+num--); } } } } } public class Test_1 { public static void main(String[] args) { sunchironize_teset r= new sunchironize_teset(); new Thread(r).start(); new Thread(r).start(); new Thread(r).start(); new Thread(r).start(); new Thread(r).start(); } }}
0x2 advanced lock and unlock methods
class MyLockStudy implements Runnable { private int count; Lock l = new ReentrantLock(); @Override public void run() { l.lock(); for (int i = 0; i < 5; i++) { System.out.println(Thread.currentThread().getName() + ": I'm doing it"); try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } l.unlock(); } public static void main(String args[]) { MyLockStudy runn = new MyLockStudy(); Thread thread1 = new Thread(runn, "thread1"); Thread thread2 = new Thread(runn, "thread2"); Thread thread3 = new Thread(runn, "thread3"); thread1.start(); thread2.start(); thread3.start(); } }
0x04 thread pool
0x1:newFixedThreadPool
1. Constructor: public static ExecutorService newFixedThreadPool(int nThreads)
2. A thread pool of fixed size is created. The created size depends on the int nThreads with the passed in construction parameters
3. If the threads in the current thread pool are full, the remaining threads will enter the queue for execution after waiting for the previous thread to finish.
4.
class Mypool_1{ public static void main(String[] args) { ExecutorService fixedThreadPool = Executors.newFixedThreadPool(3);//Create a thread pool for (int i = 0; i < 5; i++) { final int index = i; fixedThreadPool.execute(new Runnable() { @Override public void run() { SimpleDateFormat simpleDateFormat=new SimpleDateFormat( "HH:mm:ss"); System.out.println("The running time is"+simpleDateFormat.format(new Date())+" "+index); try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } } }); } fixedThreadPool.shutdown(); } //The result of execution is // The running time is 20:03:57 2 // The running time is 20:03:57 0 // The running time is 20:03:57 1 // The running time is 20:03:59 4 // The running time is 20:03:59 3 }
0x2:newCachedThreadPool
1. Constructor:
Click to view the code2. As can be seen from the construction method, it creates a cacheable thread pool. When a new task is submitted, if there is an idle thread, the task will be processed directly. If there is no idle thread, a new thread will be created to process the task, and the task will not be stored in the queuepublic static ExecutorService newCachedThreadPool() { return new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>());
class Mypool_2{ public static void main(String[] args) { ExecutorService cachedThreadPool = Executors.newCachedThreadPool(); for (int i = 0; i < 5; i++) { int index=i; cachedThreadPool.execute(new Runnable() { @Override public void run() { SimpleDateFormat sdf=new SimpleDateFormat("HH:mm:ss"); System.out.println("Running time"+sdf.format(new Date())+" "+index); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } }); } cachedThreadPool.shutdown(); // Running time 20:04:39 1 // Running time 20:04:39 3 // Running time 20:04:39 2 // Running time 20:04:39 4 // Running time 20:04:39 0 } }
0x3:newSingleThreadExecutor
1. It creates a single thread pool. It only uses a unique working thread to execute tasks, ensuring that all tasks are executed in the specified order.
2. Why single thread? Single thread execution refers to the internal thread pool. From the perspective of outside the thread pool, the main thread does not block when submitting tasks to the thread pool and is still asynchronous.
class Mypool_3{ public static void main(String[] args) { ExecutorService singethreadpool=Executors.newSingleThreadExecutor(); for (int i = 0; i < 5; i++) { int index=i; singethreadpool.execute(new Runnable() { @Override public void run() { SimpleDateFormat sdf=new SimpleDateFormat("HH:mm:ss"); System.out.println("The running time is"+sdf.format(new Date())+" "+index); try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } } }); }singethreadpool.shutdown(); // The running time is 20:37:17 0 // The running time is 20:37:19 1 // The running time is 20:37:21 2 // The running time is 20:37:23 3 // The running time is 20:37:25 4 } }
0x4:newScheduledThreadPool
1. This method creates a thread pool of fixed size to support the execution of timed and periodic tasks.
Look at deferred execution
class Mypool_4 {//Three second delayed operation public static void main(String[] args) { final SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss"); ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(3); System.out.println("Submission time: " + sdf.format(new Date())); scheduledThreadPool.schedule(new Runnable() { @Override public void run() { System.out.println("Running time: " + sdf.format(new Date())); } }, 3, TimeUnit.SECONDS); scheduledThreadPool.shutdown(); } // Submission time: 20:50:55 // Running time: 20:50:58 }
Take a look at the cycle method: use the scheduleAtFixedRate method of the thread pool to execute the task every 3 seconds after a delay of 1 second. The running results are as follows:
class Mypool_5 { public static void main(String[] args) { final SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss"); ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(3); System.out.println("Submission time: " + sdf.format(new Date())); scheduledThreadPool.scheduleAtFixedRate(new Runnable() { @Override public void run() { System.out.println("Running time: " + sdf.format(new Date())); } }, 1, 3, TimeUnit.SECONDS); try { Thread.sleep(10000); } catch (InterruptedException e) { e.printStackTrace(); } scheduledThreadPool.shutdown(); } }
0x5 summary
In fact, there are still many ways to learn about thread pool, but I'll learn about it here, and I'll have an in-depth understanding when developing java multithreading tools in the future. The following are the characteristics of each thread pool
CachedThreadPool: cacheable thread pool. There are no core threads in this thread pool. The number of non core threads is integer max_ Value is infinity. When necessary, create threads to execute tasks, and recycle threads when not needed. It is suitable for situations with less time and a large number of tasks.
SecudleThreadPool: a thread pool that periodically executes tasks. It executes tasks in threads according to a specific plan. There are core threads, but there are also non core threads. The size of non core threads is infinite. Suitable for performing periodic tasks.
SingleThreadPool: there is only one thread to execute tasks, which is applicable to the application scenario of sequential tasks.
FixedThreadPool: a thread pool with a fixed length. There are core threads. The number of core threads is the maximum number of threads. There are no non core threads
0x05 summary
The most important knowledge of multithreading is the asynchronous technology of agent pool, which will greatly improve the operation efficiency of the tools we write in the future. Worth learning