这是我参与 8 月更文挑战的第 9天,活动详情查看: 8月更文挑战
**首先我们知道有两种创建线程的方法,一种是通过new Thread类,另一种是通过使用Runnable创建线程。**这是通常情况下的创建线程的方法,但是这两种并没有我们要的返回体,所以我们需要官方再给我们提供一个创建线程的接口-->callable,除了上面的返回体,还有异常的抛出也是runnnable无法提供的;
如何实现callable
既然这样我们就按现实项目来,先是创建任务线程池
ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
设置完线程数、最大线程数、队列、空闲时间、拒绝策略后进行初始化
taskExecutor.initialize();
这里我设置的是线程数:3,最大线程数:5,队列:0,拒绝策略为交由主线程执行;
主(main)函数里执行
//线程池任务执行器初始化
ThreadPoolTaskExecutor taskExecutor = getExecutor();
for(int i = 0;i<100;i++){
Future<Boolean> booleanFuture = taskExecutor.submit(new UserMessProcessHandle("xxx"+i));
//booleanFuture.get();
}
我循环一百次来调用它,别问为啥,问就是复习多线程;巩固学习,逻辑UserMessProcessHandle方法是:
public class UserMessProcessHandle implements Callable<Boolean> {
private String note;
public UserMessProcessHandle(String note) {
this.note = note;
}
@Override
public Boolean call() throws InterruptedException {
System.out.println(Thread.currentThread().getName()+" "+note);
Thread.sleep(1000);
//other逻辑
return true;
}
}
之所以睡眠一秒,是怕打出的日志不符合我的预期;我们看下输出:
pool-1 xxx0
pool-4 xxx3
pool-3 xxx2
pool-2 xxx1
pool-5 xxx4
main xxx5
main xxx6
pool-3 xxx7
pool-4 xxx8
pool-2 xxx11
main xxx12
结果是符合预期的,默认三个线程,最大五个线程,拒绝就是main主线程执行,如果你放开booleanFuture.get(),那么他还会不停地打印true;这个的好处就是比如说你有批量对象要处理,处理过后你得要处理后的对象,那么你就可以将Future的类型变为你的对象类型,是不是觉得打开了一扇窗;
实现原理
用submit来处理是怎么处理的呢?首先他会通过ExecutorService来接收获取线程池执行器。然后调用executor.submit(task);来执行submit方法,我们看下官方对这个submit的解释;
提交一个返回值的任务以供执行,并返回一个表示任务结果的 Future。 Future 的get方法将在成功完成后返回任务的结果
顺藤摸瓜,我们再点进submit中我们看到AbstractExecutorService,这里的submit会执行通过RunnableFuture接收,创建返回一个RunnableFutur,他的对象会执行Execute方法,他的定义是在将来的某个时间执行给定的命令。 根据Executor实现的判断,该命令可以在新线程、池线程或调用线程中执行,
里面的参数是Runnable task,是不是似曾相识,是的,这里和runnable基本就是一样的了,下面有想法的同志可以继续往下探索了,基本逻辑就是这样,不停点进方法里,看实现方法和返回;