需求:将三张表的查询结果 定时保存到另一张表中
可以采用串行执行 也可以用并行执行,提高查询速度此处用并行的方式,充分利用cup资源,通过Callable接口实现多线程,实现Callable重写call方法;
实现Callable和实现Runnable类似,但是功能更强大,具体表现在:
a.可以在任务结束后提供一个返回值,Runnable不行;
b.call方法可以抛出异常,Runnable的run方法不行;
c.可以通过运行Callable得到的Fulture对象监听目标线程调用call方法的结果,得到返回值,(fulture.get(),调用后会阻塞,直到获取到返回值);
a.可以在任务结束后提供一个返回值,Runnable不行;
b.call方法可以抛出异常,Runnable的run方法不行;
c.可以通过运行Callable得到的Fulture对象监听目标线程调用call方法的结果,得到返回值,(fulture.get(),调用后会阻塞,直到获取到返回值);
1、Callable接口介绍:
(1)java.util.concurrent.Callable是一个泛型接口,只有一个call()方法;
(2)call()方法抛出异常Exception异常,且返回一个指定的泛型类对象;
2、Callable接口实现多线程的应用场景
(1)当父线程想要获取子线程的运行结果时;
3、使用Callable接口实现多线程的步骤
(1)第一步:创建Callable子类的实例化对象;
(2)第二步:创建FutureTask对象,并将Callable对象传入FutureTask的构造方法中(注意:FutureTask实现了Runnable接口和Future接口);
(3)第三步:实例化Thread对象,并在构造方法中传入FurureTask对象;
(4)第四步:启动线程;
(1)java.util.concurrent.Callable是一个泛型接口,只有一个call()方法;
(2)call()方法抛出异常Exception异常,且返回一个指定的泛型类对象;
2、Callable接口实现多线程的应用场景
(1)当父线程想要获取子线程的运行结果时;
3、使用Callable接口实现多线程的步骤
(1)第一步:创建Callable子类的实例化对象;
(2)第二步:创建FutureTask对象,并将Callable对象传入FutureTask的构造方法中(注意:FutureTask实现了Runnable接口和Future接口);
(3)第三步:实例化Thread对象,并在构造方法中传入FurureTask对象;
(4)第四步:启动线程;
@Component public class TaskDemo { @Autowired AgeMapper ageMapper; @Autowired NameMapper nameMapper; @Autowired SexMapper sexMapper; @Autowired PropertyMapper propertyMapper; @Scheduled(cron = "0 38 16 * * ?")//每天下午16:38 执行 //@Scheduled(cron = "0 0/2 0 * * ?")//每两分钟执行一次 public void test() throws ExecutionException, InterruptedException { //创建线程池 Property property = new Property(); ThreadPoolExecutor poolExecutor = (ThreadPoolExecutor) Executors.newFixedThreadPool(3); Future agefuture = poolExecutor.submit(new SelectObjectThread<>(this, "selectAgeById", new Object[]{"1"})); Future namefuture = poolExecutor.submit(new SelectObjectThread<>(this, "selectNameById", new Object[]{"1"})); Future sexfuture = poolExecutor.submit(new SelectObjectThread<>(this, "selectSexById", new Object[]{"1"})); //用do while 保证三个线程都执行完毕 do { System.out.println("任务正在执行中。。。。。"); } while (!agefuture.isDone() && !namefuture.isDone() && !sexfuture.isDone()); Age age = (Age) agefuture.get(); Name name = (Name) namefuture.get(); Sex sex = (Sex) sexfuture.get(); property.setAge(age.getAge()); property.setName(name.getName()); property.setSex(sex.getSex()); System.out.println("开始写入数据"); propertyMapper.insert(property); System.out.println("写入数据完毕"); poolExecutor.shutdown(); } public Age selectAgeById(String id) { return ageMapper.selectById("1"); } public Name selectNameById(String id) { return nameMapper.selectById("1"); } public Sex selectSexById(String id) { return sexMapper.selectById("1"); } class SelectObjectThread<T> implements Callable<T> { private Object object; private String methodName; private Object[] objects; public SelectObjectThread(Object object, String methodName, Object[] objects) { this.object = object; this.methodName = methodName; this.objects = objects; } @Override public T call() throws Exception { long start = System.currentTimeMillis(); Method method = object.getClass().getMethod(methodName, String.class);// String.class调用方法的参数类型
/* String name = method.getName();
if (name.equals("selectAgeById")){
Thread.sleep(20000);
}*/
T t = (T) method.invoke(object, objects); //System.out.println(t); long end = System.currentTimeMillis(); System.out.println("执行" + methodName + "查询用时:" + (end - start)); return t; } } }
@SpringBootApplication @MapperScan({"com.yckj.mapper"}) @EnableScheduling public class TimerApplication { public static void main(String[] args) { SpringApplication.run(TimerApplication.class, args); } }