Java Springboot 线程池使用
一、基本概念
1.进程:一个程序的执行,包含多个线程
2.线程:一个程序执行中的片段但,进程执行中的最小单位
3.使用场景:
①后台任务:定时发送大量邮件
②异步处理:统计、日志
③分布式计算、分片下载、断点续传
4.用户线程和守护线程
用户线程:程序本身执行的线程
守护线程:为程序提供通用服务的线程(GC 垃圾回收线程)
用户线程存在,JVM不会离开;用户线程执行完成退出,无论守护线程是否存在,JVM都将离开
5.同一CPU内核,同一时间,只能执行一个线程
线程调度器,分配时间片
线程优先级分为10级,1最低,10最高
6.线程的停止:采用中断
7.线程的状态:
①NEW
②RUNNABLE
③BLOCKED
④WAITING
⑤TIMED_WAITING
⑥TERMINATED
8.控制线程执行顺序:join方法(优先级是提高概率,并不绝对)
9.线程安全:子线程访问共享变量,共享变量在主内存中,访问时会将共享变量拷贝至自己的工作内存,操作完成后再写回主变量
10.Java并发编程三大特性:原子性、可见性、有序性
二、线程演示
1.线程创建
package com.atguigu.thread;
import com.sun.scenario.effect.impl.sw.sse.SSEBlend_SRC_OUTPeer;
import lombok.extern.slf4j.Slf4j;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
/**
* Description: 多线程Demo
*
* @Author:
* @Date: 2021-04-25 20:53
* @version: V1.0.0
*/
@Slf4j
public class ThreadDemo {
private static int num=10;
public static void main(String[] args) {
/**
* 采用继承的方式,只能单继承Thread
* 采用实现接口的方式,可以在实现接口的基础上再进行一次继承
* 同时,采用接口的写法可以改为匿名内部类的方式,进一步简化为Lambda表达式形式
*/
TestThread testThread = new TestThread();
testThread.start();
Thread thread = new Thread(new TestRunnable());
thread.start();
Thread threadN = new Thread(new Runnable(){
@Override
public void run(){
log.info("匿名内部类形式");
}
});
threadN.start();
Thread threadL = new Thread(()->{
log.info("Lambda表达式形式");
});
threadL.start();
/**
* 带返回值的线程
*/
FutureTask<Integer> futureTask = new FutureTask<>(new TestCallable());
Thread threadRet = new Thread(futureTask);
threadRet.start();
try {
//得到线程执行处理结果
Integer result = futureTask.get();
log.info("得到线程执行处理结果:{}",result);
}catch (ExecutionException exception) {
log.error("",exception);
}catch (InterruptedException exception) {
log.error("",exception);
}
}
/**
* 继承Thead类,实现Run方法
*/
static class TestThread extends Thread{
@Override
public void run(){
for (int i=0;i<num;i++){
log.info("Print 【{}】 Times",i);
}
}
}
/**
* 实现Runnable接口,实现Run方法
*/
static class TestRunnable implements Runnable{
@Override
public void run() {
for (int i=0;i<num;i++){
log.info("Print 【{}】 Times",i);
}
}
}
/**
* 实现Callable接口,实现带返回值的任务
*/
static class TestCallable implements Callable<Integer>{
@Override
public Integer call() throws Exception {
int sum=0;
for (int i=0;i<num;i++){
log.info("Print 【{}】 Times",i);
sum+=i;
}
return sum;
}
}
}
2.线程停止
package com.atguigu.thread;
import lombok.extern.slf4j.Slf4j;
/**
* Description: 线程停止的方法
*
* @Author:
* @Date: 2021-04-25 21:47
* @version: V1.0.0
*/
@Slf4j
public class ThreadStopDemo {
/**
* 优雅的终止线程
* threadTest.interrupt() 中断线程
* Thread.currentThread().isInterrupted() 线程是否中断
* @param args
*/
public static void main(String[] args) {
Thread threadTest = new Thread(()->{
while (true){
if(Thread.currentThread().isInterrupted()){
break;
}
log.info("线程执行中......");
}
});
threadTest.start();
/**
* 主线程休眠2秒
* 然后将子线程中断
*/
try {
Thread.sleep(2000);
threadTest.interrupt();
} catch (InterruptedException interruptedException) {
interruptedException.printStackTrace();
}
}
}
3.用户线程和守护线程
package com.atguigu.thread;
import lombok.extern.slf4j.Slf4j;
/**
* Description: 用户线程和守护线程测试
*
* @Author:
* @Date: 2021-04-25 21:27
* @version: V1.0.0
*/
@Slf4j
public class ThreadDaemonDemo {
private static int num = 100;
/**
* new Thread 默认为非守护进程
* 设置为守护进程后,当threadUser执行完成时,threadDaemon立即结束
* @param args
*/
public static void main(String[] args) {
/**
* 守护线程
*/
Thread threadDaemon = new Thread(()->{
for (int i=0;i<num;i++){
try {
Thread.sleep(200);
log.info("守护线程:【{}】",i);
} catch (InterruptedException interruptedException) {
interruptedException.printStackTrace();
}
}
});
threadDaemon.setDaemon(false);
threadDaemon.start();
/**
* 用户线程
*/
Thread threadUser = new Thread(()->{
for (int i=0;i<num;i++){
try {
Thread.sleep(50);
log.info("用户线程:【{}】",i);
} catch (InterruptedException interruptedException) {
interruptedException.printStackTrace();
}
}
});
threadUser.start();
}
}
4.线程优先级
package com.atguigu.thread;
import lombok.extern.slf4j.Slf4j;
/**
* Description: 线程优先级测试
*
* @Author:
* @Date: 2021-04-25 21:36
* @version: V1.0.0
*/
@Slf4j
public class ThreadPriority {
private static int num = 100;
/**
* 设置优先级1-10 默认为5
* @param args
*/
public static void main(String[] args) {
/**
* 守护线程
*/
Thread threadFirst = new Thread(()->{
for (int i=0;i<num;i++){
log.info("线程1:【{}】",i);
}
});
threadFirst.setPriority(1);
threadFirst.start();
/**
* 用户线程
*/
Thread threadSecond = new Thread(()->{
for (int i=0;i<num;i++){
log.info("线程2:【{}】",i);
}
});
threadSecond.setPriority(10);
threadSecond.start();
}
}
5.线程顺序执行
package com.atguigu.thread;
import lombok.extern.slf4j.Slf4j;
/**
* Description: 线程执行顺序
*
* @Author:
* @Date: 2021-04-25 22:22
* @version: V1.0.0
*/
@Slf4j
public class ThreadJoin {
private static int num = 100;
/***
* 控制线程T1、T2、T3按顺序执行
* join A { B.join() } 则A会在B执行完后执行
* @param args
*/
public static void main(String[] args) {
Thread t1 = new Thread(()->{
for (int i=0;i<num;i++){
log.info("线程0:【{}】",i);
}
});
Thread t2 = new Thread(()->{
try {
t1.join();
} catch (InterruptedException interruptedException) {
interruptedException.printStackTrace();
}
for (int i=0;i<num;i++){
log.info("线程1:【{}】",i);
}
});
Thread t3 = new Thread(()->{
try {
t2.join();
} catch (InterruptedException interruptedException) {
interruptedException.printStackTrace();
}
for (int i=0;i<num;i++){
log.info("线程2:【{}】",i);
}
});
t1.start();
t2.start();
t3.start();
}
}
6.线程安全与锁(不加锁则会出现卖票混乱)
package com.atguigu.thread;
import lombok.extern.slf4j.Slf4j;
/**
* Description: 线程安全测试
*
* @Author:
* @Date: 2021-04-25 22:53
* @version: V1.0.0
*/
@Slf4j
public class ThreadSafeDemo {
private static int tickets=100;
public static void main(String[] args) {
Object o = new Object();
Runnable runnable = ()->{
while (true){
try {
Thread.sleep(1);
} catch (InterruptedException interruptedException) {
interruptedException.printStackTrace();
}
synchronized (o){
if(tickets>0){
tickets--;
log.info("{} 卖了一张票,剩余 {}",Thread.currentThread().getName(),tickets);
}else{
break;
}
}
}
};
Thread t1 = new Thread(runnable,"窗口1");
Thread t2 = new Thread(runnable,"窗口2");
Thread t3 = new Thread(runnable,"窗口3");
t1.start();
t2.start();
t3.start();
}
}
7.线程通信演示 等待wait和唤醒notify
package com.atguigu.thread;
import lombok.extern.slf4j.Slf4j;
/**
* Description: 线程通信演示 等待:wait 唤醒:notify
*
* @Author:
* @Date: 2021-04-28 23:34
* @version: V1.0.0
*/
@Slf4j
public class ThreadCommunication {
public static void main(String[] args) {
NumMode numMode = new NumMode();
/**
* 奇数情况输出
*/
new Thread(()->{
while (true){
synchronized (numMode){
if(numMode.num<100){
if(numMode.num%2!=0){
log.info("奇数打印:{}",numMode.num);
numMode.num++;
numMode.notify();
}else{
try {
numMode.wait();
} catch (InterruptedException interruptedException) {
interruptedException.printStackTrace();
}
}
}else {
break;
}
}
}
}).start();
/**
* 偶数情况输出
*/
new Thread(()->{
while (true){
synchronized (numMode){
if(numMode.num<100){
if(numMode.num%2==0){
log.info("偶数打印:{}",numMode.num);
numMode.num++;
numMode.notify();
}else{
try {
numMode.wait();
} catch (InterruptedException interruptedException) {
interruptedException.printStackTrace();
}
}
}else {
break;
}
}
}
}).start();
}
static class NumMode{
int num=0;
}
}
8.消费和生产者模型演示 等待wait和唤醒notify
package com.atguigu.thread;
import lombok.extern.slf4j.Slf4j;
import java.util.LinkedList;
/**
* Description: 生产者消费者模型
*
* 生产者:做手机
* 消费者:买手机
* 手机店:库存容量30台
*
* @Author:
* @Date: 2021-04-28 23:57
* @version: V1.0.0
*/
@Slf4j
public class ProductionAndConsumption {
static int version = 1;
/**
* 顾客
*/
static class CustomerTask implements Runnable{
MobileShop mobileShop;
public CustomerTask(MobileShop mobileShop) {
this.mobileShop = mobileShop;
}
@Override
public void run() {
while (true){
synchronized (mobileShop){
if(mobileShop.phoneList.size()>0){
mobileShop.phoneList.poll();
mobileShop.notifyAll();
log.info(":{}购买了一台手机",Thread.currentThread().getName());
}else{
//手机抢光了
try {
mobileShop.wait();
} catch (InterruptedException interruptedException) {
interruptedException.printStackTrace();
}
}
}
}
}
}
/**
* 山寨手机厂
*/
static class ProductTask implements Runnable{
MobileShop mobileShop;
public ProductTask(MobileShop mobileShop) {
this.mobileShop = mobileShop;
}
@Override
public void run() {
while (true){
synchronized (mobileShop){
if(mobileShop.phoneList.size()<30){
Phone phone = new Phone();
phone.setModel("小米"+version);
version++;
mobileShop.phoneList.push(phone);
mobileShop.notifyAll();
log.info("{}:生产了一台手机,共{}版本了",Thread.currentThread().getName(),version);
}else{
//库存已满,停止生产
try {
mobileShop.wait();
} catch (InterruptedException interruptedException) {
interruptedException.printStackTrace();
}
}
}
}
}
}
/**
* 手机店
*/
static class MobileShop{
LinkedList phoneList = new LinkedList();
}
/**
* 手机
*/
static class Phone{
String model;
public void setModel(String model) {
this.model = model;
}
public String getModel() {
return model;
}
}
public static void main(String[] args) {
MobileShop mobileShop = new MobileShop();
new Thread(new ProductTask(mobileShop)).start();
new Thread(new CustomerTask(mobileShop)).start();
new Thread(new CustomerTask(mobileShop)).start();
}
}