其中有四个知识点我单独罗列了出来,属于多线程编程中需要知道的知识:

知识点1:X,T为泛型,为什么要用泛型,泛型和Object的区别请看:https://www.cnblogs.com/xiaoxiong2015/p/12705815.html
知识点2:线程池:https://www.cnblogs.com/xiaoxiong2015/p/12706153.html
知识点3:队列:@author Doug Lea https://www.cnblogs.com/xiaoxiong2015/p/12825636.html
知识点4:计数器,还是并发包大神 @author Doug Lea 编写。是一个原子安全的计数器,可以利用它实现发令枪
Doug Lea真是大神,编程不识Doug Lea,写尽Java也枉然,concurrent包点进去,都是他写的。可能是需要什么东西就写了吧,信手拈来的感觉。
主类:MultiThread,执行并发类
package java8test;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Callable;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.LinkedBlockingQueue; /**
* @param <H> 为被处理的数据类型
* @param <T>返回数据类型
* 知识点1:X,T为泛型,为什么要用泛型,泛型和Object的区别请看:https://www.cnblogs.com/xiaoxiong2015/p/12705815.html
*/
public abstract class MultiThread<X, T> { public static int i = 0; // 知识点2:线程池:https://www.cnblogs.com/xiaoxiong2015/p/12706153.html
private final ExecutorService exec; // 线程池 // 知识点3:@author Doung Lea 队列:https://www.cnblogs.com/xiaoxiong2015/p/12825636.html
private final BlockingQueue<Future<T>> queue = new LinkedBlockingQueue<>(); // 知识点4:计数器,还是并发包大神 @author Doug Lea 编写。是一个原子安全的计数器,可以利用它实现发令枪
private final CountDownLatch startLock = new CountDownLatch(1); // 启动门,当所有线程就绪时调用countDown private final CountDownLatch endLock; // 结束门 private final List<X> listData;// 被处理的数据 /**
* @param list list.size()为多少个线程处理,list里面的H为被处理的数据
*/
public MultiThread(List<X> list) {
if (list != null && list.size() > 0) {
this.listData = list;
exec = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors()); // 创建线程池,线程池共有nThread个线程
endLock = new CountDownLatch(list.size()); // 设置结束门计数器,当一个线程结束时调用countDown
} else {
listData = null;
exec = null;
endLock = null;
}
} /**
*
* @return 获取每个线程处理结速的数组
* @throws InterruptedException
* @throws ExecutionException
*/
public List<T> getResult() throws InterruptedException, ExecutionException { List<T> resultList = new ArrayList<>();
if (listData != null && listData.size() > 0) {
int nThread = listData.size(); // 线程数量
for (int i = 0; i < nThread; i++) {
X data = listData.get(i);
Future<T> future = exec.submit(new Task(i, data) { @Override
public T execute(int currentThread, X data) { return outExecute(currentThread, data);
}
}); // 将任务提交到线程池
queue.add(future); // 将Future实例添加至队列
}
startLock.countDown(); // 所有任务添加完毕,启动门计数器减1,这时计数器为0,所有添加的任务开始执行
endLock.await(); // 主线程阻塞,直到所有线程执行完成
for (Future<T> future : queue) {
resultList.add(future.get());
}
exec.shutdown(); // 关闭线程池
}
return resultList;
} /**
* 每一个线程执行的功能,需要调用者来实现
* @param currentThread 线程号
* @param data 每个线程被处理的数据
* @return T返回对象
*/
public abstract T outExecute(int currentThread, X data); /**
* 线程类
*/
private abstract class Task implements Callable<T> { private int currentThread;// 当前线程号 private X data; public Task(int currentThread, X data) {
this.currentThread = currentThread;
this.data = data;
} @Override
public T call() throws Exception { // startLock.await(); // 线程启动后调用await,当前线程阻塞,只有启动门计数器为0时当前线程才会往下执行
T t = null;
try {
t = execute(currentThread, data);
} finally {
endLock.countDown(); // 线程执行完毕,结束门计数器减1
}
return t;
} /**
* 每一个线程执行的功能
* @param currentThread 线程号
* @param data 每个线程被处理的数据
* @return T返回对象
*/
public abstract T execute(int currentThread, X data);
}
}
结果类:ResultVO,保存返回结果,根据实际情况替换成自己的
package java8test;

public class ResultVo {

    int i;

    public ResultVo(int i) {
this.i = i;
} public ResultVo() {
// TODO Auto-generated constructor stub
} }

参数类:ParamVO,传入参数类,根据实际情况替换成自己的
package java8test;

public class ParamVo {

    private int i;

    ParamVo(int i) {
this.i = i;
} public int getI() { return i;
} @Override
public String toString() { return String.valueOf(i) + " " + hashCode();
}
}

测试类:new两个MultiThread,可以看到MultiThread这个类不存在线程安全问题。
package java8test;

import java.util.ArrayList;
import java.util.List; public class Test { public static void main(String[] args) { try {
List<ParamVo> splitList = new ArrayList<ParamVo>();
for (int i = 0; i < 100; i++) {
splitList.add(new ParamVo(i));
}
List<ParamVo> splitList1 = new ArrayList<ParamVo>();
for (int i = 200; i < 300; i++) {
splitList1.add(new ParamVo(i));
}
MultiThread<ParamVo, ResultVo> multiThread = new MultiThread<ParamVo, ResultVo>(splitList) { @Override
public ResultVo outExecute(int currentThread, ParamVo data) { System.out.println("当前线程名称:" + Thread.currentThread().getName() + "当前线程号=" + currentThread
+ " data=" + data);
i--;
return new ResultVo(data.getI());
}
}; MultiThread<ParamVo, ResultVo> multiThread1 = new MultiThread<ParamVo, ResultVo>(splitList1) { @Override
public ResultVo outExecute(int currentThread, ParamVo data) { System.out.println("当前线程名称:" + Thread.currentThread().getName() + "当前线程号=" + currentThread
+ " data=" + data);
i--;
return new ResultVo(data.getI());
}
};
List<ResultVo> list = multiThread.getResult();
List<ResultVo> list1 = multiThread1.getResult();
// 获取每一批次处理结果
System.out.println("获取处理结果........................");
for (ResultVo vo : list) {
System.out.println(vo.i);
}
System.out.println("获取1处理结果........................");
for (ResultVo vo : list1) {
System.out.println(vo.i);
}
} catch (Exception e) {
e.printStackTrace();
} } }

这个类也用在了生产当中,用来并发插入数据。但是事务不能被管控,需要自己保证最终事务一致。需要注意。

java多线程并发执行demo,主线程阻塞的更多相关文章

  1. 多线程并发执行任务,取结果归集。终极总结:Future、FutureTask、CompletionService、CompletableFuture

    目录 1.Futrue 2.FutureTask 3.CompletionService 4.CompletableFuture 5.总结 ================正文分割线========= ...

  2. Java 多线程并发编程一览笔录

    Java 多线程并发编程一览笔录 知识体系图: 1.线程是什么? 线程是进程中独立运行的子任务. 2.创建线程的方式 方式一:将类声明为 Thread 的子类.该子类应重写 Thread 类的 run ...

  3. Java多线程并发技术

    Java多线程并发技术 参考文献: http://blog.csdn.net/aboy123/article/details/38307539 http://blog.csdn.net/ghsau/a ...

  4. Java多线程并发02——线程的生命周期与常用方法,你都掌握了吗

    在上一章,为大家介绍了线程的一些基础知识,线程的创建与终止.本期将为各位带来线程的生命周期与常用方法.关注我的公众号「Java面典」了解更多 Java 相关知识点. 线程生命周期 一个线程不是被创建了 ...

  5. 从火箭发场景来学习Java多线程并发闭锁对象

    从火箭发场景来学习Java多线程并发闭锁对象 倒计时器场景 在我们开发过程中,有时候会使用到倒计时计数器.最简单的是:int size = 5; 执行后,size—这种方式来实现.但是在多线程并发的情 ...

  6. Java多线程并发编程一览笔录

    线程是什么? 线程是进程中独立运行的子任务. 创建线程的方式 方式一:将类声明为 Thread 的子类.该子类应重写 Thread 类的 run 方法 方式二:声明实现 Runnable 接口的类.该 ...

  7. Java 多线程并发编程面试笔录一览

    知识体系图: 1.线程是什么? 线程是进程中独立运行的子任务. 2.创建线程的方式 方式一:将类声明为 Thread 的子类.该子类应重写 Thread 类的 run 方法 方式二:声明实现 Runn ...

  8. java 多线程并发问题总结

    java 多线程并发主要通过关键字synchronized实现 Java语言的关键字,当它用来修饰一个方法或者一个代码块的时候,能够保证在同一时刻最多只有一个线程执行该段代码. 一.当两个并发线程访问 ...

  9. Java多线程并发03——在Java中线程是如何调度的

    在前两篇文章中,我们已经了解了关于线程的创建与常用方法等相关知识.接下来就来了解下,当你运行线程时,线程是如何调度的.关注我的公众号「Java面典」了解更多 Java 相关知识点. 多任务系统往往需要 ...

随机推荐

  1. Rocket - util - HeterogeneousBag

    https://mp.weixin.qq.com/s/5hNM4yeQjaLvAJzgMG9PGQ   介绍HeterogeneousBag的实现.   ​​   1. 基本介绍   一个口袋(bag ...

  2. jchdl - RTL实例 - And2And(结构体嵌套的使用)

    https://mp.weixin.qq.com/s/PQIPkDymvcGc_re8ux50vA   结构体可以嵌套使用.   参考链接 https://github.com/wjcdx/jchdl ...

  3. meta个人学习纪录

    < meta > 元素 元素可提供相关页面的元信息(meta-information),比如针对搜索引擎和更新频度的描述和关键词. 标签位于文档的头部,不包含任何内容. 标签的属性定义了与 ...

  4. Magicodes.IE 在100万数据量下导入导出性能测试

    原文作者:HueiFeng 前言 目前Magicodes.IE更新到了2.2.3,感谢大家的支持,同时建议大家在使用过程中如果遇到一些问题或者说需要一些额外的功能可以直接提issues,当然更建议大家 ...

  5. Java并发编程 (五) 线程安全性

    个人博客网:https://wushaopei.github.io/    (你想要这里多有) 一.安全发布对象-发布与逸出 1.发布与逸出定义 发布对象 : 使一个对象能够被当前范围之外的代码所使用 ...

  6. JavaScript (六) js的基本语法 - - - Math 及 Date对象、String对象、Array对象

    个人博客网:https://wushaopei.github.io/    (你想要这里多有) 一.Math 1.Math对象的案例 var result= Math.max(10,20,30,40) ...

  7. (Java实现) 营救

    问题 B: 营救 时间限制: 1 Sec 内存限制: 128 MB 题目描述 铁塔尼号遇险了!他发出了求救信号.距离最近的哥伦比亚号收到了讯息,时间就是生命,必须尽快赶到那里. 通过侦测,哥伦比亚号获 ...

  8. Java实现蓝桥杯VIP算法训练 奇变的字符串

    试题 算法训练 奇变的字符串 资源限制 时间限制:1.0s 内存限制:256.0MB 问题描述 将一个字符串的奇数位(首位为第0位)取出,将其顺序弄反,再放回原字符串的原位置上. 如字符串" ...

  9. Java实现 洛谷 P1598 垂直柱状图

    题目描述 写一个程序从输入文件中去读取四行大写字母(全都是大写的,每行不超过100个字符),然后用柱状图输出每个字符在输入文件中出现的次数.严格地按照输出样例来安排你的输出格式. 输入格式 四行字符, ...

  10. java实现第三届蓝桥杯星期几

    星期几 1949年的国庆节(10月1日)是星期六. 今年(2012)的国庆节是星期一. 那么,从建国到现在,有几次国庆节正好是星期日呢? 只要答案,不限手段! 可以用windows日历,windows ...