编程语言
首页 > 编程语言> > 技术问答-7 java中的集合(2)-Collection

技术问答-7 java中的集合(2)-Collection

作者:互联网

Collection

一、方法概览

在这里插入图片描述

返回值方法说明
intsize()集合大小
booleanisEmpty()是不是包含元素(return size == 0 )
Iteratiriterator()获取迭代器
Object[]toArray()转换成Object数组
T[]toArray(T[] a)转换成指定类型的数组
booleanadd(E e)添加元素
booleanremove(Object o)删除指定元素
booleancontainsAll(Collection<?> c)是否包含结合中所有元素
booleanaddAll(Collection<? extends E> c )添加集合c中所有元素
booleanremoveAll(Collection<?> c )移出包含的c结合中的值
default booleanremoveIf(Predicate<? super E> filter )遍历数组移除符合条件的数据(JDK1.8)
booleanretainAll(Collection<?> c)仅保留此collection中那些也包含在指定collection的元素
void clear()清空集合
Spliteratorspliterator()分割数组(多线程操作JDK1.8)
Streamstream()流操作(JDK1.8)
default StreamparallelStream()并行执行的流操作

推荐一篇博客 我也是参考 水很深

二、什么是流Stream(此流非彼流)
二、parallelStream
  1. 什么是 parallelStream
    parallelStream 是一个并行执行的流,他通过默认的ForkJoinPool ,可能提高多线程任务的速度
  2. parallelStream作用
    Stream具有平行处理的能力,处理的过程会分而治之,也就是将一个大任务切分成多个小任务(跟hadoop mapreduce一个意思吧),这表示每个任务都是一个操作
    在这里插入图片描述
    输出结果~~:
    在这里插入图片描述
三、 ForkJoin
  1. ForkJoinPool是什么
    想深入研究parallelStream 我们必须先了解ForkJoin框架和ForkJonPool ,因为parallelStream 依赖于ForkJonPool ,所以这里做简单介绍
    ForkJoin框架是jdk1.7的新特性,他与ThreadPoolExecutor一样,也实现了Executor和ExecutorService接口。它使用一个无限的队列保存需要执行的任务,而线程的数量则是通过构造函数传入,如果没有构造函数中传入数据,那么就会用当前计算机可用CPU数量作为线程的默认值
    2.ForkJoinPool作用
四、窃取算法
  1. 窃取算法是什么?
    ForkJoin最核心的地方就是利用现代硬件设备多核,在一个操作的时候会有空闲的cpu,那么如何利用好这个空闲的cpu就成了提高性能的关键,而这里我们要提到工作窃取算法,工作窃取算法是整个ForkJoin的核心,工作窃取算法值某个线程从其他队列里窃取任务来执行。
  2. 为什么需要使用窃取算法?
    假如我们需要做一个比较大的任务,我们可以把这个任务分割为若干互不依赖的子任务,为了减少线程间的竞争,于是把这些子任务分别放到不同的队列里,并为每个队列创建一个独立的线程来执行队列里的任务,线程队列一一对应,比如X线程负责处理X队列里的任务。但是有的线程会先把自己手里的任务完成,而其他线程对应的队列里的任务等待处理。完成任务的线程与其等着,不如去帮其他线程做任务,于是它就去其他队里里边窃取一个任务来执行,而在这时它们会同时访问同一个队列,所以为了减少窃取任务线程和被窃取任务线程之间的竞争,通常 会使用双端队列,被窃取的线程永远从双端队列的头部拿任务执行,而窃取任务的线程永远从双端队列的尾部拿任务执行。
六、ForkJion ParallelStreams

Java8给ForkJoinPool添加了一个通用的线程池,这个线程池用来处理那些没有被显式提交到任何线程池的任务。他是ForkJoinPool类型上的一个静态元素,他拥有默认线程数量。当调用Arrays类上添加的新方法时(parallelSort ),自动并行化就会发生。
对于ForkJoinPool通用线程池的线程数量,通常使用默认值就可以了,即运行时计算机的数量。

package along;import java.util.ArrayList;import java.util.List;import java.util.Set;import java.util.concurrent.CopyOnWriteArraySet;import java.util.concurrent.CountDownLatch;public class javaTest {public static void main(String[] args) throws Exception {
		System.out.println("Hello World!");// 构造一个10000个元素的集合
		List<Integer> list = new ArrayList<>();for (int i = 0; i < 10000; i++) {
			list.add(i);}// 统计并行执行list的线程
		Set<Thread> threadSet = new CopyOnWriteArraySet<>();// 并行执行
		list.parallelStream().forEach(integer -> {
			Thread thread = Thread.currentThread();// System.out.println(thread);// 统计并行执行list的线程
			threadSet.add(thread);});
		System.out.println("threadSet一共有" + threadSet.size() + "个线程");
		System.out.println("系统一共有" + Runtime.getRuntime().availableProcessors()+ "个cpu");
		List<Integer> list1 = new ArrayList<>();
		List<Integer> list2 = new ArrayList<>();for (int i = 0; i < 100000; i++) {
			list1.add(i);
			list2.add(i);}
		Set<Thread> threadSetTwo = new CopyOnWriteArraySet<>();
		CountDownLatch countDownLatch = new CountDownLatch(2);
		Thread threadA = new Thread(() -> {
			list1.parallelStream().forEach(integer -> {
				Thread thread = Thread.currentThread();
				threadSetTwo.add(thread);});
			countDownLatch.countDown();});
		Thread threadB = new Thread(() -> {
			list2.parallelStream().forEach(integer -> {
				Thread thread = Thread.currentThread();
				threadSetTwo.add(thread);});
			countDownLatch.countDown();});

		threadA.start();
		threadB.start();
		countDownLatch.await();
		System.out.print("threadSetTwo一共有" + threadSetTwo.size() + "个线程");}}//threadSet是 4 也就是是3个线程池线程+1个forEach线程本身//threadSetTwo 是5 也就是3个线程池线程+2个forEach线程//所以如果ForkJoinPool需要4个线程 将它的值设置为 3 即可

ParallelStreams 的陷阱
parallelStreams不是万能的 不可乱用!
在这里插入图片描述
在这个例子中,我们想同时查询多个搜索引擎并且获得第一个返回的结果。

小结:

  1. 当需要处理递归分治算法时,考虑使用ForkJoinPool。
  2. 仔细设置不再进行任务划分的阈值,这个阈值对性能有影响。
  3. Java 8中的一些特性会使用到ForkJoinPool中的通用线程池。在某些场合下,需要调整该线程池的默认的线程数量。

标签:java,Thread,队列,ForkJoinPool,Collection,任务,线程,问答,窃取
来源: https://blog.51cto.com/u_12198094/2704033