为什么还要使用Spring来实现多线程呢?有两个原因,第一使用Spring比使用JDK原生的并发API更简单。第二我们的应用环境一般都会集成Spring,我们的Bean也都交给Spring来进行管理,那么使用Spring来实现多线程更加简单,更加优雅。
从Spring3同时也是新增了Java的配置方式,而且Java配置方式也逐渐成为主流的Spring的配置方式,因此后面的例子都是以Java的配置进行演示。
首先定义配置类
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import java.util.concurrent.Executor;
/**
* 方式一
* 多线程配置类
*/
@Configuration
@ComponentScan("com.xuecheng.manage_cms.service1")
@EnableAsync // 启用异步任务
public class ThreadConfig {
// 这里是声明一个bean,类似于xml中的<bean>标签。
// Executor 就是一个线程池
@Bean
public Executor getExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(5);
executor.setMaxPoolSize(10);
executor.setQueueCapacity(25);
executor.initialize();
return executor;
}
}
定义要执行的任务
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import java.util.UUID;
/**
* 多线程
* 定义要执行的方法
*/
@Service // 注解的方式把AsyncService交给Spring来管理
public class AsynTaskService {
// 这里可以注入spring中管理的其他bean,这也是使用spring来实现多线程的一大优势
@Async // 这里进行标注为异步任务,在执行此方法的时候,会单独开启线程来执行
public void f1() {
System.out.println("f1 : " + Thread.currentThread().getName() + " " + UUID.randomUUID().toString());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
@Async
public void f2() {
System.out.println("f2 : " + Thread.currentThread().getName() + " " + UUID.randomUUID().toString());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
测试类
import com.xuecheng.manage_cms.service1.AsynTaskService;
import com.xuecheng.manage_cms.service1.ThreadConfig1;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.test.context.junit4.SpringRunner;
/**
* 测试多线程
*/
@SpringBootTest
@RunWith(SpringRunner.class)
public class TestThread {
@Test
public void TestThread() {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ThreadConfig.class);
AsynTaskService service = context.getBean(AsynTaskService.class);
for (int i = 0; i < 10; i++) {
service.f1(); // 执行异步任务
service.f2();
}
context.close();
}
}
运行结果:
关于线程池的配置还有一种方式,就是直接实现AsyncConfigurer接口,重写getAsyncExecutor方法即可,代码如下:
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.AsyncConfigurer;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import java.util.concurrent.Executor;
/**
* 方式二
* 线程池的配置另一种方式,就是直接实现AsyncConfigurer接口,重写getAsyncExecutor方法即可
*/
@Configuration
@ComponentScan("com.xuecheng.manage_cms.service1")
@EnableAsync
public class ThreadConfig1 implements AsyncConfigurer {
@Override
public Executor getAsyncExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(5);
executor.setMaxPoolSize(10);
executor.setQueueCapacity(25);
executor.initialize();
return executor;
}
@Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return null;
}
}
欢迎留言讨论。