1 介绍
接本专题博客之 系统运维系列 之java中实现多线程的方式
上篇博客提到多线程使用的4种方式,分别是:
实现方式1:继承Thread类,重写该类的run方法;
实现方式2:实现Runnable接口,并重写该接口的run()方法;
实现方式3:通过Callable和FutureTask创建线程;
Callable接口实际上是属于Executor框架中的功能类,Callable接口与Runnable接口的功能类似,但提供了比Runnable更加强大的功能;Callable可以在任务结束的时候提供一个返回值,Runnable无法提供这个功能。
实现方式4:通过线程池创建线程。
方法3和4可以组合起来一起使用,首先创建线程池,然后利用FutureTask对象的get()来获取子线程执行结束的返回值用于后续程序的处理。
2 核心代码实现
//仅使用方法3实现
class MyCallable implements Callable<Integer> {
private int i = 0;
// 与run()方法不同的是,call()方法具有返回值
@Override
public Integer call() {
int sum = 0;
for (i=0; i < 10; i++) {
System.out.println(Thread.currentThread().getName() + " " + i);
sum += i;
}
return sum;
}
}
public class ThreadTest {
public static void main(String[] args) {
Callable<Integer> myCallable = new MyCallable(); // 创建MyCallable对象
FutureTask<Integer> ftask = new FutureTask<Integer>(myCallable); //使用FutureTask来包装MyCallable对象
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName() + " " + i);
if (i == 3) {
Thread thread = new Thread(ftask); //FutureTask对象作为Thread对象的target创建新的线程
thread.start(); //线程进入到就绪状态
}
}
System.out.println("主线程for循环执行完毕...");
try {
int sum = ftask.get(); //取得新创建的新线程中的call()方法返回的结果
System.out.println("sum = " + sum);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}
//仅使用方法4实现
class RunnableThread implements Runnable
{
@Override
public void run()
{
System.out.println("通过线程池方式创建的线程:" + Thread.currentThread().getName() + " ");
}
}
public class ThreadTest{
private static int POOL_NUM = 20; //线程池数量
public static void main(String[] args) throws InterruptedException {
//线程池
ExecutorService executorService = Executors.newFixedThreadPool(5);
for(int i = 0; i<POOL_NUM; i++)
{
RunnableThread thread = new RunnableThread();
//Thread.sleep(5000);
executorService.execute(thread);
//或者
executorService.submit(thread);
//execute和submit的区别:
//接收的参数不一样,submit可以是Callable、Runnable,execute只能是Runnable
//submit有返回值,而execute没有
//submit方便Exception处理
}
//关闭线程池
executorService.shutdown();
}
}
/*
首先创建线程池,然后利用FutureTask对象的get()来获取子线程执行结束的返回值用于后续程序的处理。
*/
// 创建一个临时的局部线程池(固定大小)
ExecutorService executorService = Executors.newFixedThreadPool(nThreads);
// 保存结果
List<Future<List<String>>> futures = new ArrayList<Future<List<String>>>(partions.size());
// 分配任务
for (int i = 0; i < partions.size(); i++) {
// 小任务
callTask = new CallableTest(partions.get(i));
//同步执行多个小任务
futures.add(executorService.submit(callTask));
}
// 关闭线程池
executorService.shutdown();
//获取结果
List<String> result = new ArrayList<String>();
result.addAll(future.get());
参考资料:
https://blog.csdn.net/hekf2010/article/details/86546262 多线程并行执行,然后汇总结果
https://www.cnblogs.com/huangdabing/p/9251598.html Java多线程处理List数据
https://my.oschina.net/java520me/blog/812646 java List集合中按一定数量进行分组输出
https://blog.csdn.net/kunfd/article/details/113922781?spm=1001.2101.3001.6661.1&utm_medium=distribute.pc_relevant_t0.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7Edefault-1.pc_relevant_without_ctrlist&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7Edefault-1.pc_relevant_without_ctrlist&utm_relevant_index=1 多线程处理List并将结果合并