@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

它是非常有规律的:每一个任务,都是下一条线程。然后轮回。