如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了,这样频繁创建线程就会大大降低系统的效率,因为频繁创建线程和销毁线程需要时间。
-
降低资源消耗。减少了创建和销毁线程的次数,每个工作线程都可以被重复利用,可执行多个任务。
-
提高响应速度。当任务到达时,任务可以不需要的等到线程创建就能立即执行。
-
提高线程的可管理性。可以根据系统的承受能力,调整线程池中工作线线程的数目,防止因为消耗过多的内存,而把服务器累趴下(每个线程需要大约1MB内存,线程开的越多,消耗的内存也就越大,最后死机)。
-
创建线程池对象。
-
创建Runnable接口子类对象。(task)
-
提交Runnable接口子类对象。(take task)
-
关闭线程池(一般不做)。
public class MyRunnable implements Runnable { @Override public void run() { System.out.println("我要一个教练"); try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("教练来了: " + Thread.currentThread().getName()); System.out.println("教我游泳,交完后,教练回到了游泳池"); } }
public class ThreadPoolDemo { public static void main(String[] args) { // 创建线程池对象 ExecutorService service = Executors.newFixedThreadPool(2);//包含2个线程对象 // 创建Runnable实例对象 MyRunnable r = new MyRunnable(); //自己创建线程对象的方式 // Thread t = new Thread(r); // t.start(); ---> 调用MyRunnable中的run() // 从线程池中获取线程对象,然后调用MyRunnable中的run() service.submit(r); // 再获取个线程对象,调用MyRunnable中的run() service.submit(r); service.submit(r); // 注意:submit方法调用结束后,程序并不终止,是因为线程池控制了线程的关闭。 // 将使用完的线程又归还到了线程池中 // 关闭线程池 //service.shutdown(); } }
遍历形式
// 创建线程池对象 ExecutorService service = Executors.newFixedThreadPool(8);//包含2个线程对象 // 创建Runnable实例对象 MyRunnable r = new MyRunnable(); for (int i = 0; i < 5; i++) { service.submit(()->{ System.out.println("匿名循环打印线程"); System.out.println(Thread.currentThread().getName()); }); }
做一件事情,找一个能解决这个事情的对象,调用对象的方法,完成事情.
函数式编程思想:
只要能获取到结果,谁去做的,怎么做的都不重要,重视的是结果,不重视过程
public static void main(String[] args) { new Thread(() -> System.out.println("多线程任务执行!")).start(); // 启动线程 }
接口中写法
public interface Cook { void makeFood(); } private static void invokeCook(Cook cook) { cook.makeFood(); } public static void main(String[] args) { invokeCook(() -> { System.out.println("吃饭啦!"); }); }
排序
package com.thread1; import java.util.Arrays; import java.util.Comparator; public class Person { public static void main(String[] args) { Person[] array = { new Person("古力娜扎", 19), new Person("迪丽热巴", 18), new Person("马尔扎哈", 20) }; // sortOne(array); lambda(array); } private static void lambda(Person[] array) { Arrays.sort(array,(Person p1,Person p2)->{ return p1.getAge() - p2.getAge(); }); for (Person person : array) { System.out.println(person.getAge()); } } public static void sortOne(Person[] array){ //匿名内部类 Comparator<Person> personComparable = new Comparator<Person>(){ @Override public int compare(Person o1, Person o2) { return o1.getAge()-o2.getAge(); } }; Arrays.sort(array,personComparable); for (Person person : array) { System.out.println(person.getAge()); } } private String name; private int age; 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 Person(String name, int age) { this.name = name; this.age = age; } }
-
使用Lambda必须具有接口,且要求接口中有且仅有一个抽象方法。无论是JDK内置的
Runnable
、Comparator
接口还是自定义的接口,只有当接口中的抽象方法存在且唯一时,才可以使用Lambda。 -
使用Lambda必须具有上下文推断。也就是方法的参数或局部变量类型必须为Lambda对应的接口类型,才能使用Lambda作为该接口的实例。
备注:有且仅有一个抽象方法的接口,称为“函数式接口”。
1 public class Demo { 2 /** 3 * 多线程,并行操作 4 */ 5 public void test01() throws InterruptedException { 6 ExecutorService pool = Executors.newFixedThreadPool(3); 7 CountDownLatch latch = new CountDownLatch(8); 8 for (int i = 0; i < 8; i++) { 9 try { 10 pool.submit(()->{ 11 System.out.println(Thread.currentThread().getName()); 12 }); 13 } catch (Exception e) { 14 e.printStackTrace(); 15 } finally { 16 latch.countDown(); 17 } 18 } 19 latch.await(); 20 } 21 /** 22 * 多线程,并行操作 23 */ 24 @Test 25 public void test02(){ 26 ExecutorService pool = Executors.newFixedThreadPool(3); 27 for (int i = 0; i < 8; i++) { 28 pool.submit(new Runnable() { 29 @Override 30 public void run() { 31 System.out.println(Thread.currentThread().getName()); 32 } 33 }); 34 } 35 } 36 }