Stream并发问题parallel简单展示

by yushaoyang -2018-03-11

///////////////////////////////////////////集合的线程安全问题///////////////////////////////////////////////////////
	@Test
	public void testName0() throws Exception {
		Integer[] intArray = {1, 2, 3, 4, 5, 6, 7, 8 };
		List<Integer> listOfIntegers =
		    new ArrayList<>(Arrays.asList(intArray));
//		for (Integer i : listOfIntegers) {
//			if (i==2) {
//				listOfIntegers.remove(Integer.valueOf(2));
//			}
//		}
		
		for (int i = 0; i < listOfIntegers.size(); i++) {
			if (i==1) {
				listOfIntegers.remove(Integer.valueOf(2));
			}
		}
		
	}
	
	
	//对于集合,最好避免有状态的lambda操作
	@Test
	public void testName0_1() throws Exception {
		Integer[] intArray = {1, 2, 3, 4, 5, 6, 7, 8 };
		List<Integer> listOfIntegers = new ArrayList<>(Arrays.asList(intArray));
//		listOfIntegers.stream()
//			        .filter(a -> {
//								if (a == 2) {
//									listOfIntegers.remove(Integer.valueOf(2));
//								}
//								return true;
//			        }).forEach(System.out::println);
		
		
//		listOfIntegers.stream()
//        .filter(a -> {
//					if (a == 2) {
//						listOfIntegers.add(Integer.valueOf(2));
//					}
//					return true;
//        }).forEach(System.out::println);
		
		
		 
		//这是可行的
		 List<Integer> list1 = new ArrayList<>();
		 long count = IntStream.rangeClosed(1, 1000)
				  .filter(s->list1.add(s))
		          .count();
		  System.out.println(list1.size());
		
	}
	
	
	
	/////////////////////////////////////////parallel的线程安全问题/////////////////////////////////////////////
	
	//线程安全问题  forEachOrdered:按照流的顺序遍历,牺牲了效率
	@Test
	public void foreachTest() throws Exception {
		 long s=System.currentTimeMillis();
		 List<Integer> list1 = new ArrayList<>();
		 IntStream.rangeClosed(1, 1000_0000)
		          .parallel()
                  .forEach(list1::add);
//		 System.out.println(list1);
		 System.out.println(list1.size());
		 System.out.println("花费时间:"+(System.currentTimeMillis()-s)); //2475
	}
	
	
	//需求:往List添加1000条数据
	//如何解决parallel线程安全问题
	//推荐:使用collect和reduce接口(可以支持有状态操作),如果不方便,可以使用下面的方法
	//1.尽量少用forEach来进行并发时的一些有状态操作,如果你非要用,可以用forEachOrdered代替
	//2.如果你就是要用forEach,那么可以使用安全的共享变量
	//3.可以在forEach内部加锁
	
	//推荐
	@Test
	public void foreachTest1() throws Exception {
		long s=System.currentTimeMillis();
	    List<Integer> collect = IntStream.rangeClosed(1, 1000)
							             .boxed()
							             .parallel()
					                     .collect(Collectors.toList());
		 System.out.println(collect.size());
		 System.out.println("花费时间:"+(System.currentTimeMillis()-s)); 
	}
	
	
	//方式1:使用forEachOrdered,按流顺序操作,也是并发的,不过比foreach性能低,在数据量很大的时候(比如1000_0000),才能体现他的效率,否则不如安静的用窜行;
	//即在数据量非常大的情况下:并发foreach<并发forEachOrdered<窜行
	@Test
	public void foreachTest2() throws Exception {
		 long s=System.currentTimeMillis();
		 List<Integer> list1 = new ArrayList<>();
		 IntStream.rangeClosed(1, 1000)
		          .parallel()
//		          .forEach(list1::add);
		          .forEachOrdered(list1::add);
		 System.out.println(list1);
		 System.out.println(list1.size());
		 System.out.println("花费时间:"+(System.currentTimeMillis()-s));
	}
	
	//方式2:使用安全的共享变量
	@Test
	public void foreachTest3() throws Exception {
		 long s=System.currentTimeMillis();
		 List<Integer> list1 =  Collections.synchronizedList(new ArrayList<>());
		 IntStream.rangeClosed(1, 1000)
		          .parallel()
		          .forEach(list1::add);
		 
		 System.out.println(list1);
		 System.out.println(list1.size());
		 System.out.println("花费时间:"+(System.currentTimeMillis()-s));
	}
	
	//方式3:forEach内部加锁
	@Test
	public void foreachTest4() throws Exception {
	  	Lock lock = new ReentrantLock();
		 long s=System.currentTimeMillis();
		 List<Integer> list1 =  new ArrayList<>();
		 IntStream.rangeClosed(1, 1000)
		          .parallel()
		          .forEach(cc->{
		        	  lock.lock();
		        	  list1.add(cc) ;
		        	  lock.unlock();
		          });
		 System.out.println(list1);
		 System.out.println(list1.size());
		 System.out.println("花费时间:"+(System.currentTimeMillis()-s));
	}

	
	
	
	/////////////////////////////parallel有状态操作///////////////////////////////////////////////////////
	//前面说到:有状态操作可能会影响并发
	@Test
	public void testName3() throws Exception {
		IntStream.generate(()->(int)(Math.random()*100))
		         .limit(50)
		         .parallel()
		         .sorted()
		         .peek(s->System.out.println(Thread.currentThread().getName()))
		         .forEach(System.out::println);
	}
	
	@Test
	public void testName4() throws Exception {
		 List<Integer> list = IntStream.generate(()->8)
		.limit(50)
		.boxed()
		.parallel()
		.peek(s->System.out.println(Thread.currentThread().getName()))
		.distinct()
//		.peek(s->System.out.println(Thread.currentThread().getName()))
		.collect(Collectors.toList());
		 Collections.sort(list);
		 System.out.println(list);
	}
	
	


猜你喜欢

转载自blog.csdn.net/u011165335/article/details/79518602
今日推荐