Article directory
1. Basic concepts
- Program
A program is an ordered collection of instructions and data - Process
The process of executing a program
Process is the unit of system resource allocation - Thread
A process includes one or more threads. A thread
is the unit of CPU scheduling and execution.
Threads are executed independently.
Notice:
Multithreading refers to multiple
CPU
(ie multi-core) performing different tasks at the same time.One can only execute one thread
CPU
on the same node
2. How to create a process
- inherit
Thread class
- accomplish
Runnable interface
- accomplish
Callable interface
Thread class
AchievedRunnable interface
The JVM allows an application to execute multiple threads of execution concurrently
2.1 Priority of threads
Each thread has a priority
Higher priority threads execute before lower priority threads
The priority of the new thread is initially set to the priority of the creating thread
When a new thread is created within a thread, the new thread is a daemon thread if and only if the creating thread is a daemon process.
2.2 main thread stops
When the JVM starts, there is usually a non-daemon thread (usually calling a method main
named ). The JVM will continue executing the thread until one of the following occurs:
Runtime
The method of the class has been calledexit
, and the security manager has allowed the exit operation- Total death of all non-daemon threads
2.3 Create a new thread
2.3.1 Thread
- inherit
Thread
class - rewrite
run()
main()
methodnew
of this class and callstart()
/**
* description: 线程学习
* @author: Leet
* @date: 2020-11-10 23:25
**/
public class TestThread1 extends Thread{
@Override
public void run() {
for (int i = 0; i < 2000; i++) {
System.out.println(String.format("%s%d", "我在看代码---", i));
}
}
public static void main(String[] args) {
new TestThread1().start();
for (int i = 0; i < 2000; i++) {
System.out.println(String.format("%s%d", "我在学习多线程---", i));
}
}
}
2.3.2 Runnable
- accomplish
Runnable
- rewrite
run()
main()
Innew
one of this class is passed as a parameter toThread
the object , callstart()
/**
* description: 多线程学习2
*
* @author: Leet
* @date: 2020-11-10 23:39
**/
public class TestThread2 implements Runnable {
@Override
public void run() {
for (int i = 0; i < 2000; i++) {
System.out.println(String.format("%s%d", "我是天才-----", i));
}
}
public static void main(String[] args) {
new Thread(new TestThread2()).start();
for (int i = 0; i < 2000; i++) {
System.out.println(String.format("%s%d", "不,我才是天才-----", i));
}
}
}
2.3.3 Callable
- accomplish
Callable interface
- Override
call()
method , need to throw an exception - Create target object XXX
- Create an execution service:
ExecutorService es = Executors.newFixedThreadPool(1);
- Submit for execution:
Future<Boolean> result = es.submit(XXX);
- Get the result:
boolean r = result.get();
- Close the service:
es.shutdown();
3. Static proxy mode
Both the real object and the proxy object implement the same interface
The proxy object proxies the real character
package proxy;
/**
* description:静态代理学习
* 通过“结婚”这个场景带入
* @author Leet
* @date 2020/11/11 9:31
*/
public interface Marry {
void marry();
}
class You implements Marry {
@Override
public void marry() {
System.out.println("今天我要结婚了,我很高兴");
}
}
class WeddingCompany implements Marry {
public WeddingCompany(Marry marrier) {
this.marrier = marrier;
}
private Marry marrier;
@Override
public void marry() {
before();
marrier.marry();
after();
}
private void before() {
System.out.println("结婚前,婚庆公司布置现场");
}
private void after() {
System.out.println("结婚后,婚庆公司打扫现场");
}
}
class TestStaticProxy {
public static void main(String[] args) {
WeddingCompany weddingCompany = new WeddingCompany(new You());
weddingCompany.marry();
}
}
3.1 Proxy in Thread class
Thread 类
Runnable interface
Proxy implementation class
4. lambda
- Functional interface
The interface has only one method
When using this interface to implement a class, you can use lambda
public class Main {
public static void main(String[] args) {
new Thread(() -> System.out.println("lambda 创建线程")).start();
}
}
Lambda expressions are comfortable to use in stream programming of containers
5. Thread state
5.1 Thread method
setPriority(int newPriority) | Change thread priority |
static void sleep(long milis) | Let the thread sleep for milis ms |
void join() | wait for the thread to terminate |
static void yield() | Suspend the thread and execute other threads (Let Yin) |
isAlive() | whether the thread is alive |
5.1.1 Thread stop
- Use a limited number of times to stop the thread
- Use a
flag
(terminate loop) to let the thread stop - Do not use
stop()
,destory()
(discarded)
5.1.2 Thread sleep
sleep()
Exceptions need to be caught:InterruptedException
sleep does not release the lock
After the insomnia time is reached, the thread enters the ready state
5.1.3 Thread politeness
yield()
Thread courtesy: Let the current thread stop, but not block, become ready
Courtesy doesn't necessarily mean success
5.1.4 join()
Merge threads, wait for this thread to finish executing, and then execute other threads (other threads are blocked at this time)
/**
* description: join() 方法测试
* @author: Leet
* @date: 2020-11-11 11:06
**/
public class TestJoin implements Runnable {
@Override
public void run() {
for (int i = 0; i < 1000; i++) {
System.out.printf("%s%d\n", "线程 VIP 来了 ---》 ", i);
}
}
public static void main(String[] args) throws InterruptedException {
Thread thread = new Thread(new TestJoin());
thread.start();
for (int i = 0; i < 500; i++) {
if (i == 200) {
thread.join();
}
System.out.printf("%s%d\n", "线程 main ---》 ", i);
}
// main :VIP 线程属实过分了,它自己执行那么多次,不老实排队,竟然利用自己的特权插队,这是可恶。
}
}
5.2 Observe thread status:Thread.State
5.3 Thread priority
Java provides priority for each thread
The thread scheduler decides which thread to schedule according to the priority
- Priority just means the high or low probability of being scheduled
- Thread priority: 1~10
- get thread priority
getPriority()
- Set thread priority
setPriority(int priority)
Suggestion: Priority is set start()
before
/**
* description: 线程优先级测试
*
* @author: Leet
* @date: 2020-11-11 11:26
**/
public class TestPriority implements Runnable {
@Override
public void run() {
System.out.printf("%S 的 priority : %d\n", Thread.currentThread().getName(), Thread.currentThread().getPriority());
}
public static void main(String[] args) {
System.out.printf("%S 的 priority : %d\n", Thread.currentThread().getName(), Thread.currentThread().getPriority());
Thread thread1 = new Thread(new TestPriority(), "thread1");
Thread thread2 = new Thread(new TestPriority(), "thread2");
Thread thread3 = new Thread(new TestPriority(), "thread3");
Thread thread4 = new Thread(new TestPriority(), "thread4");
Thread thread5 = new Thread(new TestPriority(), "thread5");
thread1.setPriority(1);
thread2.setPriority(5);
thread2.setPriority(9);
thread4.setPriority(2);
thread5.setPriority(10);
thread1.start();
thread2.start();
thread3.start();
thread4.start();
thread5.start();
}
}
5.4 Daemon threads
setDaemon(true)
Make this thread a daemon thread- The user thread ends, regardless of the daemon thread, and the JVM (program) stops
/**
* description: 守护线程
* @author: Leet
* @date: 2020-11-11 14:15
**/
public class TestDaemon {
public static void main(String[] args) {
Thread thread = new Thread(new God());
thread.setDaemon(true);
thread.start();
new Thread(new You()).start();
}
}
class God implements Runnable {
@Override
public void run() {
while (true) {
System.out.println("GOD BLESS YOU");
}
// 你到天堂,见到 GOD
// GOD: 我还没反应过来,你咋就死了????!!!!!
}
}
class You implements Runnable {
@Override
public void run() {
for (int i = 0; i < 36500; i++) {
System.out.println("You are happy every day");
}
System.out.println("----------Goodbye! The world----------");
}
}
6. Thread synchronization
6.1 Queues and locks
- For a large number of unified resource access, you can use the queue
- In order to solve access conflicts, when accessing, add a lock mechanism to synchronize
a thread to obtain an exclusive lock on the object. This thread monopolizes the resource, and other threads must wait until the thread releases the lock.- existing problems
- Threads that have not acquired the lock are suspended
- Performance loss:
- scheduling
- priority
- existing problems
6.2 Unsafe example
- buy tickets
- withdraw money
- container
6.3 Synchronization method
By private
ensuring that data can only be accessed by objects, synchronized
mechanisms are proposed for methods (acting on methods or blocks) to ensure synchronization.
For ordinary synchronization methods, the lock is the current instance object. If there are multiple instances, the lock objects must be different and synchronization cannot be completed.
For static synchronized methods, the lock is on the current class Class 对象
. There are multiple instances, but the lock object is the same, and synchronization can be completed
For synchronized method blocks, the lock is a configuration object enclosed in synchronized
parentheses .
6.4 Deadlock
Multiple threads each occupy some shared resources, and wait for the resources occupied by other threads to run, resulting in a situation where two or more threads are waiting for each other to release resources and stop
When a synchronization block holds the locks of more than two objects at the same time, a "deadlock" problem may occur
package synchronizedtest.deadsynchronized;
/**
* description: 验证死锁
* 死锁:多个线程互相持有各自需要的资源,而僵持
* synchronized 块同时持有两个以上对象的锁,就可能造成死锁
*
* @author: Leet
* @date: 2020-11-11 15:25
**/
public class DeadLock {
public static void main(String[] args) {
// 灰姑娘想化妆,她拿起了口红
new Thread(new Makeup(0, "灰姑娘")).start();
// 白雪公主想化妆,她拿起了镜子
new Thread(new Makeup(1, "白雪公主")).start();
}
}
/**
* 口红
*/
class Lipstick {
}
/**
* 镜子
*/
class Mirror {
}
/**
* 化妆
*/
class Makeup implements Runnable {
static Lipstick lipstick = new Lipstick();
static Mirror mirror = new Mirror();
int choice;
String girlName;
public Makeup(int choice, String girlName) {
this.choice = choice;
this.girlName = girlName;
}
@Override
public void run() {
try {
makeup();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
/**
* lipstick 与 mirror 是 Makeup 类的静态属性,为 Makeup 类对象持有;
* lipstick 与 mirror只有一个,
* 所以说,下方同步块中的代码,锁共享资源的方法正确
*/
private void makeup() throws InterruptedException {
if (choice == 0) {
synchronized (lipstick) {
System.out.printf("%s 获得口红\n", girlName);
Thread.sleep(1000);
}
synchronized (mirror) {
System.out.printf("%s 获得镜子\n", girlName);
}
} else {
synchronized (mirror) {
System.out.printf("%s 获得镜子\n", girlName);
Thread.sleep(2000);
}
synchronized (lipstick) {
System.out.printf("%s 获得口红\n", girlName);
}
}
}
}
7. Thread cooperation
What I learned before is that each thread does its own work, and it has nothing to do with each other and does not interfere with each other.
Now it's time to get the threads to work together!
7.1 Producer and consumer model
Producer and Consumer Problems
Assuming that only one product can be stored in the warehouse, the producer puts the produced product into the warehouse, and the consumer takes the product out of the warehouse for consumption
If there is no product in the warehouse, then the producer puts the product in the warehouse, otherwise stops production and waits until something in the warehouse is picked up by the consumer
If there is a product in the warehouse, then the consumer will take the product away for consumption, otherwise stop consuming and wait until there is a product in the warehouse again
This is a thread synchronization problem, the two share the same resource, depend on each other, and are mutually conditioned.
Obviously, just using synchronized
is not enough: synchronized
message passing between different threads cannot be achieved.
7.2 Thread communication
wait() | Let the thread wait until notified by other threads without holding (releasing) the lock |
wait(long timeout) | Let the thread wait for the specified number of milliseconds |
notify() | Wake up a waiting thread |
notifyAll() | Wake up all threads that call the wait() method on the same class, and threads with higher priority are scheduled first |
Note: They are all methods Object 类
in and must be called in a synchronized block, otherwise throwIllegalMonitorStateException
7.3 Solutions
7.3.1 Tube method
Set a buffer with a certain capacity, the producer produces something into the buffer, and the consumer consumes from the buffer
Judging which thread to wake up and which thread to wait according to the state of the buffer capacity
package thread.synchronize;
/**
* description: 生产者与消费者问题:管程法解决
*
* @author: Leet
* @date: 2020-11-12 19:58
**/
public class TestPC {
public static void main(String[] args) {
SynContainer container = new SynContainer();
new Productor(container).start();
new Consumer(container).start();
}
}
class Productor extends Thread {
SynContainer container;
public Productor(SynContainer container) {
this.container = container;
}
@Override
public void run() {
for (int i = 0; i < 100; i++) {
try {
container.push(new Chicken(i));
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.printf("生产了 %d 只鸡\n", i);
}
}
}
class Consumer extends Thread {
SynContainer container;
public Consumer(SynContainer container) {
this.container = container;
}
@Override
public void run() {
for (int i = 0; i < 100; i++) {
try {
System.out.printf("消费了---> %d 只鸡\n", container.pop().id);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class Chicken {
int id;
public Chicken(int id) {
this.id = id;
}
}
class SynContainer {
Chicken[] chickens = new Chicken[10];
int count = 0;
/**
* 生产者放入产品
* @param chicken 产品
* @throws InterruptedException InterruptedException
*/
public synchronized void push(Chicken chicken) throws InterruptedException {
// 如果容器满了,需要等待消费者消费
if (count == chickens.length) {
wait();
} else {
// 容器没满,生产者直接放入产品
chickens[count++] = chicken;
// 通知消费者消费
notifyAll();
}
}
/**
* 消费者消费
* @return Chicken Chicken
* @throws InterruptedException InterruptedException
*/
public synchronized Chicken pop() throws InterruptedException {
// 如果容器空了,消费者等待(等待生产者向容器中放入产品)
if (count == 0) {
this.wait();
} {
// 容器中有产品,消费者直接消费
Chicken chicken = chickens[--count];
// 告知生产者生产东西
notifyAll();
return chicken;
}
}
}
7.3.2 Signal light method
Set an identifier, and judge which thread to wake up and which thread to wait according to the state of the identifier
package thread.synchronize;
/**
* description: 生产者与消费者问题:信号灯法解决
*
* @author: Leet
* @date: 2020-11-12 20:32
**/
public class TestPC2 {
public static void main(String[] args) {
TV tv = new TV();
new Player(tv).start();
new Watcher(tv).start();
}
}
class Player extends Thread {
TV tv;
public Player(TV tv) {
this.tv = tv;
}
@Override
public void run() {
for (int i = 0; i < 20; i++) {
if (i % 2 == 0) {
this.tv.play("Hello World 播放中");
} else {
this.tv.play("抖音:记录记录美好生活");
}
}
}
}
class Watcher extends Thread {
TV tv;
public Watcher(TV tv) {
this.tv = tv;
}
@Override
public void run() {
tv.watch();
}
}
class TV {
String voice;
/**
* true: 演员表演,观众等待
* false: 观众观看,演员等待
*/
boolean flag = true;
public synchronized void play(String voice) {
if (!flag) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.printf("演员表演了 %s\n", voice);
notifyAll();
this.voice = voice;
this.flag = !this.flag;
}
public synchronized void watch() {
if (flag) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.printf("观众观看了 %s\n", voice);
notifyAll();
this.flag = !this.flag;
}
}
This example is a bit flawed: it will deadlock.
Then please be smart and change it.
8. Thread pool
ExecutorService
thread pool interfacevoid execute(Runnable command)
Runnable 接口
Execute implementation class<T> Future <T> submit(Callable<T> task)
Callable 接口
Execute implementation classvoid shutdown()
Close the thread pool
Executor
Factory classes for tool classes and thread pools
are used to create and return different types of thread pools
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* description: 线程池
*
* @author: Leet
* @date: 2020-11-12 20:57
**/
public class TestThreadPool implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
public static void main(String[] args) {
ExecutorService es = Executors.newFixedThreadPool(10);
es.execute(new TestThreadPool());
es.execute(new TestThreadPool());
es.execute(new TestThreadPool());
es.execute(new TestThreadPool());
es.shutdown();
}
}