多线程
package com.learn.basic.thired.四种创建线程的方式;
import java.util.concurrent.*;
/**
* 1.继承Thread
* 2.实现接口Runnable
* 3.实现接口Callable 之后+FutureTask(可以拿到返回结果,可以处理异常)
* 4.线程池
*/
public class ThreadDemo {
//创建线程池
public static ExecutorService service = Executors.newFixedThreadPool(5);
public static void main(String[] args) throws ExecutionException, InterruptedException {
/**
* 1.Thread
*/
new Thread01().start();
/**
* 2.Runnable
*/
new Thread(new Runnable01()).start();
/**
* 3.Callable
* FutureTask继承关系可以看到,它就是一个Runnable
*/
FutureTask<Integer> integerFutureTask = new FutureTask<>(new Callable01());
new Thread(integerFutureTask).start();
//阻塞等待任务执行完,取任务返回结果
Integer integer = integerFutureTask.get();
System.out.println(integer);
/**
* 4.线程池本质都是[ExecutorService]
* 可以执行Runnable,或Callable(当线程池只有一个线程时,可以看到每次用的线程都是同一个)
*/
service.submit(new Runnable01());
Future<Integer> submit = service.submit(new Callable01());
System.out.println(submit.get());
}
public static class Thread01 extends Thread {
@Override
public void run() {
System.out.println("线程" + Thread.currentThread().getName());
}
}
public static class Runnable01 implements Runnable {
@Override
public void run() {
System.out.println("线程" + Thread.currentThread().getName());
}
}
/**
* Callable允许异步任务有返回值
*/
public static class Callable01 implements Callable<Integer> {
@Override
public Integer call() {
System.out.println("线程" + Thread.currentThread().getName());
int i = 10 / 2;
return i;
}
}
}
package com.learn.basic.thired;
/**
* @author 11695
*/
public class ThreadTest {
/**
* 多线程卖票的例子,多次运行发现结果有负数(线程安全问题)
* 解决:在while循环里加上synchronized ()
* @param args
*/
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
Thread thread = new Thread(new Ticket());
thread.start();
}
}
static class Ticket implements Runnable {
private static int i =10;
@Override
public void run() {
while (i>0){
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(i--);
}
}
}
}
package com.learn.basic.thired.线程池;
import java.util.concurrent.*;
/**
* ThreadPoolExecutor的七大参数
* int corePoolSize,核心线程数【一直存在】
* int maximumPoolSize,最大线程数
* long keepAliveTime,存活时间(线程数 - 核心线程数 = 多余的线程 多余的线程空闲时间大于存活时间,将被释放)
* TimeUnit unit,存活时间的单位
* BlockingQueue<Runnable> workQueue,阻塞队列(任务数250>最大线程数50),将未能执行的200个任务放入队列(当线程空闲时就会取队列里的任务),new LinkedBlockingDeque<>(),默认是Integer的最大值。会导致内存不足,最好自己指定
* ThreadFactory threadFactory,线程的创建工厂(如制定线程的名称)Executors.defaultThreadFactory()默认线程工厂
* RejectedExecutionHandler handler,阻塞队列满了,按照制定的拒绝策略,拒绝执行任务
* 拒绝策略:DiscardOldestPolicy丢弃老任务
* CallerRunsPolicy不丢弃,同步调用
* AbortPolicy直接丢弃新任务,并抛异常
* DiscardPolicy直接丢弃新任务,不抛异常
*
* <p>
* 工作顺序:
* 1.创建线程池,准备core数量的线程
* 2.core满了,再进来的任务放入阻塞队列
* 3.阻塞队列满了,开新线程,直到最大线程数
* 4.最大线程数满了。按照制定的拒绝策略,拒绝执行任务(如果不想拒绝还要执行)
* 5.任务执行完毕,空闲线程的空闲时间大于存活时间,就释放
*/
public class ThreadPoolDemo {
public static void main(String[] args) {
//原生方式new出来
ThreadPoolExecutor executor = new ThreadPoolExecutor(5,
200,
10,
TimeUnit.SECONDS,
new LinkedBlockingDeque<>(100000),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.AbortPolicy());
/**
* 使用Executors创建常见的4种线程池
* newCachedThreadPool:核心线程数0,所有线程都可回收,无界队列
* newFixedThreadPool:固定大小的线程池,核心线程数=最大线程数,所有线程都不可回收,无界队列
* newScheduledThreadPool:定时任务的线程池,无界队列
* newSingleThreadExecutor: 核心线程数=最大线程数=1,该线程池只有一个线程,无界队列,队列大小为Integer的最大值
*/
Executors.newCachedThreadPool();
Executors.newFixedThreadPool(10);
Executors.newScheduledThreadPool(10);
Executors.newSingleThreadExecutor();
}
}
-
springboot项目中使用配置类配置线程池
package com.learn.mybatis.plus.config;
import org.apache.tomcat.util.threads.ThreadPoolExecutor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.task.AsyncTaskExecutor;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.TimeUnit;
@Configuration
public class ThreadConfig {
/**
* ThreadPoolExecutor创建线程池
* @return
*/
@Bean("threadPoolExecutor")
public ThreadPoolExecutor threadPoolExecutor() {
ThreadPoolExecutor taskExecutor = new ThreadPoolExecutor(5,
10,
10,
TimeUnit.SECONDS,
new LinkedBlockingDeque<>(100000),
Executors.defaultThreadFactory(),
new java.util.concurrent.ThreadPoolExecutor.AbortPolicy());
return taskExecutor;
}
/**
* ThreadPoolTaskExecutor 创建线程池
* 无界队列,最好指定下队列大小,任务太多会内存溢出,线程的最大值也没了意义
* @return
*/
@Bean("taskExecutor")
public AsyncTaskExecutor taskExecutor() {
ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
taskExecutor.setMaxPoolSize(10);
taskExecutor.setCorePoolSize(5);
taskExecutor.setThreadNamePrefix("线程名称");
taskExecutor.initialize();
return taskExecutor;
}
}
-
异步注解@Async的使用
springBoot启动类上添加注解@EnableAsync开启异步调用
在service的实现类里面创建方法,在其他类中调用(本类调用无效同@Transactional,原因spring的动态代理)
/**
* 使用上面创建的线程池 @Async("线程池的名称")
*/
@Async("threadPoolExecutor")
public void testAsync() {
System.out.println(Thread.currentThread().getName());
}
-
ForkJoinPool的使用配合java8并行流parallelStream
package com.learn.basic.thired.forkjoin;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ForkJoinTask;
public class ForkJoinDemo {
public static void main(String[] args) throws InterruptedException, ExecutionException {
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9);
ForkJoinPool forkJoinPool = new ForkJoinPool(50);
ForkJoinTask<?> forkJoinTask = forkJoinPool.submit(() -> {
list.parallelStream().forEach(System.out::println);
}
);
forkJoinTask.get();
}
}