不要把守护进程和守护线程相提并论!守护进程在后台运行运行,不需要和用户交互,本质和普通进程类似。而守护线程就不一样了,当其他所有的非守护线程结束之后,守护线程是自动结束,也就是说,Java中所有的线程都执行完毕后,守护线程自动结束,因此守护线程不适合进行IO操作,只适合打打杂:

  1. public static void main(String[] args) throws InterruptedException{
  2. Thread t = new Thread(() -> {
  3. while (true){
  4. try {
  5. System.out.println("程序正常运行中...");
  6. Thread.sleep(1000);
  7. } catch (InterruptedException e) {
  8. e.printStackTrace();
  9. }
  10. }
  11. });
  12. t.setDaemon(true); //设置为守护线程(必须在开始之前,中途是不允许转换的)
  13. t.start();
  14. for (int i = 0; i < 5; i++) {
  15. Thread.sleep(1000);
  16. }
  17. }

在守护线程中产生的新线程也是守护的:

  1. public static void main(String[] args) throws InterruptedException{
  2. Thread t = new Thread(() -> {
  3. Thread it = new Thread(() -> {
  4. while (true){
  5. try {
  6. System.out.println("程序正常运行中...");
  7. Thread.sleep(1000);
  8. } catch (InterruptedException e) {
  9. e.printStackTrace();
  10. }
  11. }
  12. });
  13. it.start();
  14. });
  15. t.setDaemon(true); //设置为守护线程(必须在开始之前,中途是不允许转换的)
  16. t.start();
  17. for (int i = 0; i < 5; i++) {
  18. Thread.sleep(1000);
  19. }
  20. }

再谈集合类并行方法

其实我们之前在讲解集合类的根接口时,就发现有这样一个方法:

  1. default Stream<E> parallelStream() {
  2. return StreamSupport.stream(spliterator(), true);
  3. }

并行流,其实就是一个多线程执行的流,它通过默认的ForkJoinPool实现(这里不讲解原理),它可以提高你的多线程任务的速度。

public static void main(String[] args) {
    List<Integer> list = new ArrayList<>(Arrays.asList(1, 4, 5, 2, 9, 3, 6, 0));
    list
            .parallelStream()    //获得并行流
            .forEach(i -> System.out.println(Thread.currentThread().getName()+" -> "+i));
}

我们发现,forEach操作的顺序,并不是我们实际List中的顺序,同时每次打印也是不同的线程在执行!我们可以通过调用forEachOrdered()方法来使用单线程维持原本的顺序:

public static void main(String[] args) {
    List<Integer> list = new ArrayList<>(Arrays.asList(1, 4, 5, 2, 9, 3, 6, 0));
    list
            .parallelStream()    //获得并行流
            .forEachOrdered(System.out::println);
}

我们之前还发现,在Arrays数组工具类中,也包含大量的并行方法:

public static void main(String[] args) {
    int[] arr = new int[]{1, 4, 5, 2, 9, 3, 6, 0};
    Arrays.parallelSort(arr);   //使用多线程进行并行排序,效率更高
    System.out.println(Arrays.toString(arr));
}

更多地使用并行方法,可以更加充分地发挥现代计算机多核心的优势,但是同时需要注意多线程产生的异步问题!

public static void main(String[] args) {
    int[] arr = new int[]{1, 4, 5, 2, 9, 3, 6, 0};
    Arrays.parallelSetAll(arr, i -> {
        System.out.println(Thread.currentThread().getName());
        return arr[i];
    });
    System.out.println(Arrays.toString(arr));
}

通过对Java多线程的了解,我们就具备了利用多线程解决问题的思维!