多线程学习之Callable接口和Future类
一、将启动多线程类封装在线程类中,实现Thread类,重写run方法满足的需求
public class MyThread extends Thread{
private List<List<Integer>> list;
private List<String> resultList;
public MyThread(List<List<Integer>> list,List<String> resultList) {
this.list = list;
this.resultList = resultList;
}
//重写run方法满足自己的需求
@Override
public void run() {
int threadNum = list.size() > 50?50:list.size();
//使用Future集合接受每个任务线程执行的结果
List<Future<Object>> futureList = new ArrayList<>();
//创建线程池
ExecutorService pool = Executors.newFixedThreadPool(threadNum);
for (int i = 0;i<list.size();i++){
//启动多线程执行任务
futureList.add(pool.submit(new MyTesk(list.get(i))));
}
//循环得到每个任务线程执行结果,并将其返回
for (int i = 0;i<futureList.size();i++){
Future<Object> objectFuture = futureList.get(i);
try {
while (true){
if(objectFuture.isDone() && objectFuture.isCancelled()){//若任务已经完成
List<String> result = (List<String>) objectFuture.get();
//处理结果
resultList.addAll(result);
} else {
Thread.sleep(100);//线程睡眠等待线程处理完成
}
break;//跳出本次循环
}
} catch (Exception e) {
e.printStackTrace();
}
}
pool.shutdown();
}
}
二、编写每个线程类的执行任务,实现Callable接口,重写call方法满足自己的需求
public class MyTesk implements Callable{
private List<Integer> list;
public MyTesk(List<Integer> list) {
this.list = list;
}
@Override
public List<String> call() throws Exception {
List<String> list = new ArrayList<>();
for (int i = 0;i<list.size();i++){
String s = "第"+list.get(i)+"次说我爱你中国";
list.add(s);
}
return list;
}
}
三、主方法中启动run方法
public static void main(String[] args) {
List<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
list.add(4);
list.add(5);
List<List<Integer>> paramList = getLists(list,2);
List<String> result = new ArrayList<>();
MyThread myThread = new MyThread(paramList,result);
System.out.println("参数的集合为"+paramList.size());
//启动线程
myThread.run();
System.out.println("多线程结果"+result.size());
for (int i = 0;i<result.size();i++){
System.out.println(result.get(i));
}
}
四、总结
1.Thread类中,run方法和start方法的区别。run方法是由当前线程执行Thread类中的run方法体中的代码。须等待run方法完成后,才能执行后续代码。而start方法创建了另一个线程执行run方法体中的代码,无须等待run方法中代码完成,达到一个异步的作用。
2.用实现Callable接口来创建线程,可实现完成线程的任务后,返回完成后的结果。同时用List<Future>集合对返回结果进行接收。
3.线程池的创建和使用。
//创建线程池
ExecutorService pool = Executors.newFixedThreadPool(threadNum);
//线程池的使用
pool.submit(new MyTesk(list.get(i)));
其中线程池还有一种使用方法:pool.execute(实现runnable接口的类);这种方法适用于无需方法结果的需求。
五、另一种启动异步线程方法
package work;
import java.util.concurrent.Executors;
public class YBThread {
public void startYBThread(){
Executors.newCachedThreadPool().submit(new Runnable() {
@Override
public void run() {
//异步线程执的代码逻辑
}
});
}
}