• java8新特性


    1.HashMap和HashSet

    如果说当某一个链表的大小大于8,总容量大于64,那么就会把链表转换成红黑树结构(二叉树的一种),除了添加以外其他的效率都比链表快,所以现在的结构是数组加链表加红黑树

    2.ConcurrentHashMap<K,V>

    使用大量的cas算法,且取消原来的16段机制,采用了链表和红黑树

    3.方法区

    原来称为非堆(但是占用jvm空间),现在直接分离出来了叫做元空间,直接占用物理内存。

    4.lambda表达式

    函数式接口:只包含一个抽象方法的接口,称为函数式接口,使用@FunctionalInterface注解,这样做可以检查它是否是一个函数式接口。

    适用前提条件:必须是一个函数式接口

    定义:lambda表达式表示的是一个匿名的函数,Lambda 操作符“->”左侧:指定了Lambda 表达式需要的所有参数,右侧:指定了Lambda 体(匿名函数方法的方法体),即Lambda 表达式要执行的功能。

    左侧:在无参的条件下(),有参只有一个参数的前提下可以写成(x),当然也可以去掉()写成x,多个参数的情况下都需要带()

    右侧:无返回值只用一条语句可以不带{},多条语句需要带{},有返回值只有一条语句无{}情况下无需写return,多条或者有{}时需要写rreturn

    原因:在加载编译的时候会自判断后编译成class字节码文件,在效率上在以前的基础上并没有提升,只是书写较为方便

    public class LambdaTest1 {
    	 public  static  void testA(LambdaTest1A la){
    		 la.testA();
    	 }
         public static void main(String[] args) {
        	 testA(()->System.out.println("hello testA"));
        	 ArrayList<Integer> list = new  ArrayList<>();
        	 list.add(321);
        	 list.add(123);
        	 list.add(342);
        	 list.add(112);
        	 //Collections.sort(list,(x,y)->x-y);从小到大
        	 Collections.sort(list,(x,y)->y-x);//从大到小
        	 System.out.println(list);
    	}
    }
    interface   LambdaTest1A{
    	   void  testA();
    }
    
    //策略设计模式
    public class LambdaTest2 {
    	public static List<LambdaTest2Person> test(List<LambdaTest2Person> list, Predicate<LambdaTest2Person> t) {
    		ArrayList<LambdaTest2Person> list2 = new ArrayList<>();
    		for (LambdaTest2Person lambdaTest2Person : list) {
    			if (t.test(lambdaTest2Person)) {
    				list2.add(lambdaTest2Person);
    			}
    		}
    		return list2;
    	}
    
    	public static void main(String[] args) {
    		ArrayList<LambdaTest2Person> list = new ArrayList<>();
    		list.add(new LambdaTest2Person("张三", 24, 3333));
    		list.add(new LambdaTest2Person("李四", 34, 8888));
    		list.add(new LambdaTest2Person("王五", 15, 5555));
    		list.add(new LambdaTest2Person("赵六", 34, 6666));
    		//List<LambdaTest2Person> test = test(list, (x) -> x.getAge() > 30);
    		//System.out.println(test);// 年龄大于35岁的
    		Collections.sort(list, (x, y) -> {
    			if (x.getAge() == y.getAge()) {
    				return x.getSalary() - y.getSalary();
    			}
    			return x.getAge() - y.getAge();
    		});// 先按年龄从小到大排列,年龄相同那么按工资从小到大排列
    		for (LambdaTest2Person lambdaTest2Person : list) {
    			System.out.println(lambdaTest2Person);
    		}
    
    	}
    }
    
    class LambdaTest2Person {
    	private String name;
    	private int age;
    	private int salary;
    
    	public String getName() {
    		return name;
    	}
    
    	public void setName(String name) {
    		this.name = name;
    	}
    
    	public int getAge() {
    		return age;
    	}
    
    	public void setAge(int age) {
    		this.age = age;
    	}
    
    	public int getSalary() {
    		return salary;
    	}
    
    	public void setSalary(int salary) {
    		this.salary = salary;
    	}
    
    	public LambdaTest2Person(String name, int age, int salary) {
    		this.name = name;
    		this.age = age;
    		this.salary = salary;
    	}
    
    	public LambdaTest2Person() {
    	}
    
    	@Override
    	public String toString() {
    		return "LambdaTest2Person [name=" + name + ", age=" + age + ", salary=" + salary + "]";
    	}
    
    }
    

     4.java8内置的函数式接口

    Consumer<T>   void accept(T t)

    Supplier<T>    T get()

    Function<T, R>  R apply(T t)

    Predicate<T>  boolean test(T t);

    BiFunction<T,U,R>  R apply(T t,U u)

    UnaryOperator<T>  T apply(T t)

    BinaryOperator<T>  T apply(T t1,T t2)

    BiConsumer<T,U>   void accept(T t,U u)

    ToIntFunction<T>   参数T  返回值 int

    IntFunction<R>  参数int  返回R

    public class LambdaTest3 {
         public static void main(String[] args) {
        	 Consumer<String>   cm=(x)->System.out.println(x);
        	 cm.accept("consumer");
        	 Supplier<String>   sp=()->"Supplier";
        	 System.out.println(sp.get());
        	 Function<String, Integer>  fu= x-> Integer.valueOf(x);
        	 System.out.println(fu.apply("12"));
        	 Predicate<Integer> pr=(x)-> x>0;
        	 System.out.println(pr.test(5));
        	 BiFunction<Integer,Integer, Integer>  bi=(x,y)->x+y;
        	 System.out.println(bi.apply(2, 3));
    	}
    }
    

     5.方法引用与构造器引用及数组引用

    方法引用

    对象::实例方法    ;     类::静态方法       ;类::实例方法      ;    构造器引用    ;    类名 :: new   ;    数组引用     ;    类型[] :: new

    public class LambdaTest4 {
         public static void main(String[] args) {
        	 //自我推测是建立在编译的前提下的,编译时一行一行的,例如如下
        	 String [] str={"a","b"};//成立
        	 //str={"a","b"};//编译不通过
        	 //编译时能自我推测  对象::实例方法
        	 Consumer<String>   cm=System.out::println;
        	 cm.accept("Consumer");
        	 //类::静态方法,编译时一行一行的
        	 BiFunction<Integer,Integer, Integer>  bi=Integer::compare;
        	 System.out.println(bi.apply(1, 2));
        	 //类名实例方法
        	 Function<LambdaTest2Person, Integer> fu=LambdaTest2Person::getAge;
        	 System.out.println(fu.apply(new LambdaTest2Person("张三", 23, 3333)));
        	 //类名::new   
        	 Supplier<LambdaTest2Person>  person=LambdaTest2Person::new;
        	 //无参构造
        	 LambdaTest2Person lambdaTest2Person = person.get();
        	 System.out.println(lambdaTest2Person);
        	 //类型[] :: new 
        	 Function<Integer, LambdaTest2Person[]> fun2 = LambdaTest2Person[] :: new;
        	 LambdaTest2Person[] emps = fun2.apply(20);
     		 System.out.println(emps.length);
    	}
    }
    

     6.stream流

    定义:数据渠道,用于操作数据源(集合、数组等)所生成的元素序列

    特点:Stream 自己不会存储元素。

    Stream 不会改变源对象。相反,他们会返回一个持有结果的新Stream。

    Stream 操作是延迟执行的。这意味着他们会等到需要结果的时候才执行。

    也就是说需要结束以后才有结果

    public class StreamTest2 {
      public static void main(String[] args) {
    	//获取流的方式1
    	 ArrayList<String> list = new ArrayList<>();
    	 Stream<String> stream = list.stream();
    		// 获取流的方式2
    		String[] strs = new String[10];
    		Stream<String> stream2 = Arrays.stream(strs);
    		// 获取流的方式3
    		Stream<String> of = Stream.of("a", "b");
    		// 创建无线流
    		// 迭代   static <T> UnaryOperator<T> identity() {return t -> t;},0表示起始值
    		Stream<Integer> iterate = Stream.iterate(0, (x) -> x - 2);
    		iterate.limit(10).forEach(System.out::println);
    		System.out.println("-----------------");
    		// 创建无限流
    		// 生成  
    		//T get();
    		Stream<Double> generate = Stream.generate(() -> Math.random());
    		generate.limit(10).forEach(System.out::println);
    	}
    }
    
    public class StreamTest1 {
      public static void main(String[] args) {
    	  ArrayList<LambdaTest2Person> list = new ArrayList<>();
    		list.add(new LambdaTest2Person("张三", 24, 3333));
    		list.add(new LambdaTest2Person("李四", 34, 8888));
    		list.add(new LambdaTest2Person("王五", 15, 5555));
    		list.add(new LambdaTest2Person("赵六", 34, 6666));
    		Stream<LambdaTest2Person> stream = list.stream();
    		Stream<LambdaTest2Person> stream1 = list.stream();
    		Stream<LambdaTest2Person> stream2 = list.stream();
    		Stream<LambdaTest2Person> stream3 = list.stream();
    		// filter--  boolean test(T t);
    		stream.filter((x)->x.getAge()>25).forEach(System.out::println);
    		System.out.println("-----------------------");
    		/*
    		 * LambdaTest2Person [name=李四, age=34, salary=8888]
    		 * LambdaTest2Person [name=赵六, age=34, salary=6666]
    		 */
    		//limit 显示的个数
    		stream1.filter((x)->x.getAge()>25).limit(1).forEach(System.out::println);
    		//LambdaTest2Person [name=李四, age=34, salary=8888]
    		System.out.println("-----------------------");
    		//skip跳过几个
    		stream2.filter((x)->x.getAge()>25).skip(1).forEach(System.out::println);
    		//LambdaTest2Person [name=赵六, age=34, salary=6666]
    		System.out.println("-----------------------");
    		//distinct()根据hashcode去重,需要重写hashcode,这里就根据相同年龄去重
    		stream3.filter((x)->x.getAge()>25).distinct().forEach(System.out::println);
    		//LambdaTest2Person [name=李四, age=34, salary=8888]
      }
    }
    
    class LambdaTest2Person {
    	private String name;
    	private int age;
    	private int salary;
    
    	public String getName() {
    		return name;
    	}
    
    	public void setName(String name) {
    		this.name = name;
    	}
    
    	public int getAge() {
    		return age;
    	}
    
    	public void setAge(int age) {
    		this.age = age;
    	}
    
    	public int getSalary() {
    		return salary;
    	}
    
    	public void setSalary(int salary) {
    		this.salary = salary;
    	}
    
    	public LambdaTest2Person(String name, int age, int salary) {
    		this.name = name;
    		this.age = age;
    		this.salary = salary;
    	}
    
    	public LambdaTest2Person() {
    	}
    
    	@Override
    	public String toString() {
    		return "LambdaTest2Person [name=" + name + ", age=" + age + ", salary=" + salary + "]";
    	}
         //hashcode根据年龄去重
    	@Override
    	public int hashCode() {
    		final int prime = 31;
    		int result = 1;
    		result = prime * result + age;
    		return result;
    	}
    
    	@Override
    	public boolean equals(Object obj) {
    		if (this == obj)
    			return true;
    		if (obj == null)
    			return false;
    		if (getClass() != obj.getClass())
    			return false;
    		LambdaTest2Person other = (LambdaTest2Person) obj;
    		if (age != other.age)
    			return false;
    		return true;
    	}
    }
    
    public class StreamTest2 {
    	public static   Stream<Character> toUpper(String str){
    		ArrayList<Character> list = new  ArrayList<>();
    		for (Character character : str.toUpperCase().toCharArray()) {
    			list.add(character);
    		}
    		return  list.stream();
    	}
    	public static void main(String[] args) {
    		System.out.println("----------");
    		ArrayList<LambdaTest2Person> list = new ArrayList<>();
    		list.add(new LambdaTest2Person("张三", 24, 3333));
    		list.add(new LambdaTest2Person("李四", 34, 8888));
    		list.add(new LambdaTest2Person("王五", 15, 5555));
    		list.add(new LambdaTest2Person("赵六", 34, 6666));
    		// map逐个遍历映射 获取名字 张三 李四 王五 赵六
    		List<String> collect2 = list.stream().map((x) -> x.getName()).collect(Collectors.toList());
    		collect2.stream().forEach(System.out::println);
    		System.out.println("----------");
    		//flatMap与map的区别
    		//首先是map 返回的是     Stream<Stream<Character>>        
    		Stream<Stream<Character>> map = Stream.of("aa","bb").map(StreamTest2::toUpper);
    		//然后是flatMap Stream<Character>
    		Stream<Character> flatMap = Stream.of("aa","bb").flatMap(StreamTest2::toUpper);
    		// sort排序  按年龄排序  王五 张三 李四 赵六
    		System.out.println("----------");
    		list.stream().sorted((x, y) -> x.getAge() - y.getAge()).map((x) -> x.getName()).collect(Collectors.toList())
    				.forEach(System.out::println);
    		//count  统计 2 2 
    		Long collect =  Stream.of(1, 2, 3, 4, 5).filter((x) -> x > 3).map((x) -> 1).collect(Collectors.counting());
    		long count = Stream.of(1, 2, 3, 4, 5).filter((x) -> x > 3).map((x) -> 1).count();
    		System.out.println(collect);
    		System.out.println(count);
    		System.out.println("----------");
    		//allMatch  是否所有的都匹配  false  
    		boolean allMatch = list.stream().allMatch((x)-> "张三".equals (x.getName()));
    		System.out.println(allMatch);
    		//anyMatch  是否一个匹配 true
    		boolean anyMatch = list.stream().anyMatch((x)-> "张三".equals (x.getName()));
    		System.out.println(anyMatch);
    		//noneMatch  没有匹配  false
    		boolean noneMatch = list.stream().noneMatch((x)-> "张三".equals (x.getName()));
    		System.out.println(noneMatch);
    		System.out.println("----------");
    		//findFirst()  返回第一个元素  张三
    		String string = list.stream().map((x)->x.getName()).findFirst().get();
    		System.out.println(string);
    		//findAny()  返回年龄为34的其中的任何一个人 
    		LambdaTest2Person lambdaTest2Person = list.stream().filter((x)->x.getAge()==34).findAny().get();
    		System.out.println(lambdaTest2Person);
    		//返回最大值(也有可能是最小值) 这个是根据排序来的
    		Integer integer = Stream.of(1,3,2,4,10,3,2).max((x,y)->x-y).get();
    		System.out.println(integer);
    		//返回最小值(也有可能是最大值) 这个是根据排序来的
    		Integer integer1 = Stream.of(1,3,2,4,10,3,2).max(Integer::compare).get();
    		System.out.println(integer1);
    		System.out.println("----------");
    		//reduce   根据所写的逐个计算,下面是求和  21  31
    		Integer integer2 = Stream.of(1,2,3,4,5,6).reduce((x,y)->x+y).get();
    		System.out.println(integer2);
    		//10表示起始值
    		Integer integer3 = Stream.of(1,2,3,4,5,6).reduce(10,(x,y)->x+y);
    		System.out.println(integer3);
    	}
    }
    
    public class StreamTest4 {
    	public static void main(String[] args) {
    		// collect(Collector c) 这个可以求和,平均值,求最大值,分组,保存到集合等
    		// 求平均值
    		Double collect = Stream.of(1, 3, 2, 4, 6).filter((x) -> x > 3).collect(Collectors.averagingInt((x) -> x));
    		System.out.println(collect);
    		System.out.println("----------");
    		// 去重1 2 3 4 6
    		Stream.of(1, 3, 2, 4, 6, 6, 6, 4).collect(Collectors.toSet()).forEach(System.out::println);
    		;
    		System.out.println("----------");
    		// 先去重后分组 {大于3=[4, 6], 小于3=[1, 2, 3]}
    		Map<String, List<Integer>> collect2 = Stream.of(1, 3, 2, 4, 6, 6, 6, 4).collect(Collectors.toSet()).stream()
    				.collect(Collectors.groupingBy((x) -> {
    					if (x > 3) {
    						return "大于3";
    					} else {
    						return "小于3";
    					}
    				}));
    		System.out.println(collect2);
    		// 多级分组
    		ArrayList<LambdaTest2Person> list = new ArrayList<>();
    		list.add(new LambdaTest2Person("张三", 24, 3333));
    		list.add(new LambdaTest2Person("李四", 34, 8888));
    		list.add(new LambdaTest2Person("王五", 15, 5555));
    		list.add(new LambdaTest2Person("赵六", 34, 6666));
    		Map<String, Map<String, List<LambdaTest2Person>>> collect3 = list.stream().collect(Collectors.groupingBy((x) -> {
    			if (x.getAge() > 25) {
    				return "大于25";
    			} else {
    				return "小于25";
    			}
    		}, Collectors.groupingBy((x) -> {
    			if (x.getSalary() > 4000) {
    				return "大于4000";
    			}else {
    				return "小于4000";
    			}
    		})));
    		//{大于25={大于4000=[LambdaTest2Person [name=李四, age=34, salary=8888], LambdaTest2Person [name=赵六, age=34, salary=6666]]}, 
              //小于25={大于4000=[LambdaTest2Person [name=王五, age=15, salary=5555]], 小于4000=[LambdaTest2Person [name=张三, age=24, salary=3333]]}} System.out.println(collect3); } }

    7.java8的局部内部类的变更

       public static void main(String[] args) {
    	   //当局部内部类使用外部的变量是会自动的添加final,在jdk1.7之前需要手动的添加
    	   	  int  i=3;//在jdk1.7之前 这个前面需要添加 final ,但在jdk1.8后会自己添加
    //	   	  i=5//编译错误
    		  class LocalInnerTest{
    			  public void test(){
    				  System.out.println(i);
    			  }
    		  }
      }
    

     8.fork/join框架

     fork/join,将一个大任务,进行拆分(fork)成若干个小任务(拆到不可再拆时),再将一个个的小任务运算的结果进行join 汇总.

     工作窃取模式,充分利用多核线程;

     工作窃取:当一个线程执行完了,别的没有执行完,那么该线程会随机的去别的线程的末尾进行窃取工作任务,前提是多核cpu

    //jdk1.7之前的算法   传统的算法
    public class ForkJoinCalculate extends RecursiveTask<Long> {
    	public static void main(String[] args) {
    		long start = System.currentTimeMillis();
    
    		ForkJoinPool pool = new ForkJoinPool();
    		ForkJoinTask<Long> task = new ForkJoinCalculate(0L, 10000000000L);
    
    		long sum = pool.invoke(task);
    		System.out.println(sum);
    
    		long end = System.currentTimeMillis();
    
    		System.out.println("耗费的时间为: " + (end - start));
    	}
    
    	private static final long serialVersionUID = 13475679780L;
    
    	private long start;
    	private long end;
    
    	private static final long THRESHOLD = 100000L; // 临界值
    
    	public ForkJoinCalculate(long start, long end) {
    		this.start = start;
    		this.end = end;
    	}
    
    	@Override
    	protected Long compute() {
    		long length = end - start;
    
    		if (length <= THRESHOLD) {
    			long sum = 0;
    
    			for (long i = start; i <= end; i++) {
    				sum += i;
    			}
    
    			return sum;
    		} else {
    			long middle = (start + end) / 2;
    
    			ForkJoinCalculate left = new ForkJoinCalculate(start, middle);
    			left.fork(); // 拆分,并将该子任务压入线程队列
    
    			ForkJoinCalculate right = new ForkJoinCalculate(middle + 1, end);
    			right.fork();
    
    			return left.join() + right.join();
    		}
    
    	}
    
    }
    
    public class NewForkJoin {
    	@Test
    	//顺序流,单线程的
    	//parallel() 与sequential() 在并行流与顺序流之间进行切换。
        public  void  serialStream(){
        	long asLong = LongStream.rangeClosed(0, 10000000L).reduce(Long::sum).getAsLong();
        	long sum = LongStream.rangeClosed(0, 10000000L).sum();
        	System.out.println(asLong);
        	System.out.println(sum);
        }
    	@Test
    	//并行流  多线程的
    	public  void  parallelStream1(){
    		long sum = LongStream.rangeClosed(0, 10000000L).parallel().sum();
        	System.out.println(sum);
        }
    }
    

     9.optional

    目的:尽量的减少空指针异常,属于一个容器类,表示一个值存在或者不存在

    public class OptionalTest {
    	
        public static void main(String[] args) {    	
    		//Optional<String> of = Optional.of(null);// 创建一个 Optional 实例,也会报异常,指定在这一行
    		Optional<Object> empty = Optional.empty();//创建一个空的 Optional 实例
    		System.out.println(empty.toString());//Optional.empty
    		Optional<Object> ofNullable = Optional.ofNullable(null);//若 t 不为 null,创建 Optional 实例,否则创建空实例
    		Object orElse = Optional.ofNullable(null).orElse("大帅哥");//如果调用对象包含值,返回该值,否则返回t
    		System.out.println(orElse);//大帅哥
    		boolean present = Optional.ofNullable(null).isPresent();// 判断是否包含值
    		System.out.println(present);//false
    		Object orElseGet = Optional.ofNullable(null).orElseGet(()->"大帅哥");//orElseGet(Supplier s) :如果调用对象包含值,返回该值,否则返回 s 获取的值
    		System.out.println(orElseGet);//大帅哥
    		//map(Function f): 如果有值对其处理,并返回处理后的Optional,否则返回 Optional.empty()
    		//flatMap(Function mapper):与 map 类似,要求返回值必须是Optional
    	}
    }
    

    10.接口中的新定义

    类优先,接口中都实现,那么就按需加载(需要时指定),在Java 8中,在接口中添加静态方法带来了一个限制 :这些方法不能由实现它的类继承。

    public class InterfaceTest extends InterfaceTestC implements InterfaceTestA,InterfaceTestB{
    	public static void main(String[] args) {
                InterfaceTest interfaceTest = new InterfaceTest();
                interfaceTest.testA();//InterfaceTestC:testA优先使用类中的方法
                interfaceTest.testB();//InterfaceTestB---Override--testB,优先使用类中的方法
                
    	}
    
    	@Override
    	public void testB() {
    		System.out.println("InterfaceTestB---Override--testB");
    	}
    
    	@Override
    	public void testC() {
    		InterfaceTestA.super.testC();//多个需要重写一个使用的方法,静态方法需要用接口名调用
    	}
    
    }
    
    interface InterfaceTestA {
    	static void testA() {// 没有默认会添加public,只能是public的
    		System.out.println("InterfaceTestA:testA");
    	}
    
    	default void testB() {/// 没有默认会添加public,只能是public的
    		System.out.println("InterfaceTestA:testB");
    	}
    	default void testC() {// 没有默认会添加public,只能是public的
    		System.out.println("InterfaceTestA:testC");
    	}
    }
    
    interface InterfaceTestB {
    	void testB();// 默认添加public abstract
    	default void testC() {// 没有默认会添加public,只能是public的
    		System.out.println("InterfaceTestB:testC");
    	}
    }
    
    class InterfaceTestC {
    	void testA() {// 没有默认会添加public,只能是public的
    		System.out.println("InterfaceTestC:testA");
    	}
    }
    

    11.重复注解

    java8后可以重复注解@Repeatable

    public class AnnotationTest {
    
    	@MyAnnotation("a") // @Repeatable没有这个之前,不能按如下这么写
    	@MyAnnotation("b")
    	public void test() {
    
    	}
    
    	public static void main(String[] args) throws NoSuchMethodException, SecurityException {// 获取方法上的注解
    		Class<? extends AnnotationTest> class1 = new AnnotationTest().getClass();
    		Method method = class1.getMethod("test");
    		// MyAnnotation annotation =
    		// method.getAnnotation(MyAnnotation.class);//只有一次注解的时候能这么做,重复注解的则不行null
    		MyAnnotation[] annotationsByType = method.getAnnotationsByType(MyAnnotation.class);// 重复注解可以这样
    		for (MyAnnotation myAnnotation : annotationsByType) {
    			System.out.println(myAnnotation.value());
    		}
    	}
    }
    
    @Repeatable(MyAnnotations.class)//添加该注解,需要一个该注解的容器,例如@interface MyAnnotations  MyAnnotation[] value();
    @Target({ ElementType.METHOD, ElementType.TYPE, ElementType.FIELD })
    @Retention(RetentionPolicy.RUNTIME)
    @interface MyAnnotation {
    	String value() default "adu";
    }
    
    @Target({ ElementType.METHOD, ElementType.TYPE, ElementType.FIELD })
    @Retention(RetentionPolicy.RUNTIME)
    @interface MyAnnotations {
    	MyAnnotation[] value();
    }
    

     12.新时间api

    java8的时间api先线程安全的,而以前的是线程不安全的

    //存在线程安全问题,java.util.concurrent.ExecutionException异常偶尔会出现;
    public class OldTimeTest {
    	public static void main(String[] args) throws InterruptedException, ExecutionException {
    		SimpleDateFormat sdf = new SimpleDateFormat();
    		sdf.applyPattern("yyyy-MM-dd");
    		FutureTask<Date> futureTask = new FutureTask<>(() -> {
    			return sdf.parse("2018-5-5");
    		});
    		ExecutorService newFixedThreadPool = Executors.newFixedThreadPool(10);
    		Future<?> submit2 = newFixedThreadPool.submit(futureTask);
    		System.out.println(submit2.get());// null
    
    		Callable<Date> task = new Callable<Date>() {
    			@Override
    			public Date call() throws Exception {
    				return sdf.parse("2018-5-5");
    			}
    		};
    		List<Future<Date>> list = new ArrayList<>();
    		for (int i = 0; i < 9; i++) {
    			list.add(newFixedThreadPool.submit(task));
    		}
    		newFixedThreadPool.shutdown();
    		for (Future<Date> future : list) {
    			System.out.println(future.get());// callable的不为空
    		}
    	}
    }
    

     old的解决方法

    public class ThreadLocalTest {
    	private static  ThreadLocal<DateFormat> threadLocal = new ThreadLocal<DateFormat>() {
    		@Override
    		protected DateFormat initialValue() {
    			return new SimpleDateFormat("yyyy-MM-dd");//每次都产生一个新的DateFormat解决线程安全问题
    		}
    
    	};
    	/**
    	 * format:yyyy-MM-dd
    	 * 
    	 * @param str
    	 * @throws ParseException
    	 * @return
    	 */
    	public  static Date  getDate(String str) throws ParseException{
    		return threadLocal.get().parse(str);
    	}
    }
    
    public class OldTimeTest {
    	public static void main(String[] args) throws InterruptedException, ExecutionException {
    		ExecutorService newFixedThreadPool = Executors.newFixedThreadPool(10);
    		Callable<Date> task = new Callable<Date>() {
    			@Override
    			public Date call() throws Exception {
    				return ThreadLocalTest.getDate("2018-5-5");
    			}
    		};
    		List<Future<Date>> list = new ArrayList<>();
    		for (int i = 0; i < 10; i++) {
    			list.add(newFixedThreadPool.submit(task));
    		}
    		newFixedThreadPool.shutdown();
    		for (Future<Date> future : list) {
    			System.out.println(future.get());
    		}
    	}
    }
    

     新的时间api  使用ISO-8601标准

    //DateTimeFormatter    LocalDate
    public class NewLocalDateTime {
        public static void main(String[] args) throws InterruptedException, ExecutionException {
        	DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        	ExecutorService newFixedThreadPool = Executors.newFixedThreadPool(10);
    		Callable<LocalDate> task = new Callable<LocalDate>() {
    			@Override
    			public LocalDate call() throws Exception {
    				return LocalDate.parse("2018-05-05", df);//格式需要完全一致"2018-5-5"就不行
    			}
    		};
    		List<Future<LocalDate>> list = new ArrayList<>();
    		for (int i = 0; i < 10; i++) {
    			list.add(newFixedThreadPool.submit(task)) ;
    		}
    		for (Future<LocalDate> future : list) {
    			System.out.println(future.get());
    		}
    		newFixedThreadPool.shutdown();
    	}
    }
    
    //DateTimeFormatter    LocalDate
            public void main(String[] args) throws InterruptedException, ExecutionException {
                Instant now = Instant.now();//默认使用 UTC 时区  +8h
                System.out.println(now);//2018-08-05T07:23:22.110Z
                OffsetDateTime atOffset = now.atOffset(ZoneOffset.ofHours(8));
                long l = atOffset.toInstant().toEpochMilli();
                System.out.println(atOffset);//2018-08-05T15:23:22.110+08:00
                long epochMilli = now.toEpochMilli();
                System.out.println(epochMilli);// System.currentTimeMillis()  new Date().getTime()
                System.out.println("----------------");
                LocalDateTime localDateTime=LocalDateTime.now();//获取本地时间
                DateTimeFormatter df=DateTimeFormatter.ofPattern("yyyy年MM月dd天hh时mm分ss秒");
                String format = localDateTime.format(df);//
                System.out.println(format);
                System.out.println("----------------");
                LocalDateTime parse = LocalDateTime.parse("2006年5月6日", df);
                Instant oldTime = Instant.now();
                Thread.sleep(1000);
                Instant newTime = Instant.now();
                Duration between = Duration.between(oldTime, newTime);
                System.out.println(between.getSeconds());//1s
                //Period.between(ld2, ld1);  年月天 时间差
                //ZonedDate、ZonedTime、ZonedDateTime : 带时区的时间或日期
                //LocalDateTime ldt = LocalDateTime.now(ZoneId.of("Asia/Shanghai"));
        }
    
  • 相关阅读:
    Linux
    SpringData JPA复合主键
    SpringData JPA实现CRUD,分页与多参数排序
    springboot自定义配置文件
    drools入门示例
    Java 自定义注解与注解解析实例
    GitHub创建项目,保存代码。
    SpringAOP的应用实例与总结
    springmvc与fastjson的整合,注解@RequestBody的使用
    graphviz画图与中文乱码等问题总结
  • 原文地址:https://www.cnblogs.com/gg128/p/9416414.html
Copyright © 2020-2023  润新知