Spring 中的 @Async 和 @Scheduled 理解
Contents
@Async
spring-test.xml
文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:task="http://www.springframework.org/schema/task"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/task
http://www.springframework.org/schema/task/spring-task-3.2.xsd">
<task:annotation-driven scheduler="myScheduler" executor="myExecutor"/>
<task:executor id="myExecutor" pool-size="20"/>
<task:scheduler id="myScheduler" pool-size="5"/>
<bean id="hello" class="hello.world.task.TestTask" />
</beans>
spring官网例子
import java.util.concurrent.Future;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
@Service
public class GitHubLookupService {
RestTemplate restTemplate = new RestTemplate();
@Async
public Future<User> findUser(String user) throws InterruptedException {
System.out.println("Looking up " + user);
User results = restTemplate.getForObject("https://api.github.com/users/" + user, User.class);
// Artificial delay of 1s for demonstration purposes
Thread.sleep(1000L);
return new AsyncResult<User>(results);
}
}
Async动作类
package hello.world.task;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncResult;
import java.util.concurrent.Future;
/**
* Created by yang on 15-12-3.
*/
public class TestTask {
@Async
public Future<String> run() throws InterruptedException {
System.out.println(Thread.currentThread().getName());
Thread.sleep(20 * 1000);
return new AsyncResult<String>("hello");
}
}
java测试类
package hello.world;
import hello.world.task.TestTask;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
/**
* Created by yang on 15-11-9.
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:spring-test.xml")
public class HelloTest {
@Autowired
private TestTask testTask;
@Test
public void run() throws ExecutionException, InterruptedException {
Future<String> hello = testTask.run();
System.out.println("after 20 s?");
String h = hello.get();
System.out.println(h);
}
}
以上,它是以myexecutor
的线程池来执行的.
@Scheduled
将@Async
改为@Scheduled
public class TestTask {
@Scheduled(cron = "*/2 * * * * *")
public void run() throws InterruptedException {
System.out.println(Thread.currentThread().getName());
}
}
看执行结果,它是以myscheduler
的线程池来执行的,而且返回值只能是void
.
同时使用 @Scheduled 和 @Async
不过注意,如果这样子使用了,异步执行的返回结果Future
就不要这样子使用了,这时返回值只能是void
.
同时使用这两个注解的效果,相当于@Scheduled
负责调度,而executor
负责执行。
看打印的线程可知:
myExecutor-1
myExecutor-2
myExecutor-3
myExecutor-4
myExecutor-5
myExecutor-6
myExecutor-7
myExecutor-8
myExecutor-9
myExecutor-10
myExecutor-11
myExecutor-12
myExecutor-13
myExecutor-14
myExecutor-15
myExecutor-16
它是非常有规律的:每一个任务,都是下一条线程。然后轮回。