Android开发 - Thread 线程UI主线程与后台运行多线程解析

什么是线程

  • 线程就像是一条小路允许程序在运行时同时做多件事。可以把它想象成一条跑道上跑步的跑者而整个程序就是操场

线程的基本概念

  • 线程是程序执行的基本单元。每个程序至少有一个线程(主线程),它负责执行程序中的代码

  • 多线程多个线程同时在运行,类似于操场上有多个跑步的跑者。这样可以让程序同时做更多的事情,例如同时下载文件和处理用户输入

为什么要用线程

  • 提高效率线程允许程序同时进行多项任务,例如:
    • 下载文件的同时显示进度条
    • 处理数据的同时响应用户点击
  • 改善用户体验:如果一个应用程序只使用主线程(UI线程)来做所有的工作,比如下载数据读取文件,用户界面可能会变得迟缓无响应。使用线程可以避免这种情况保持应用流畅

线程的工作原理

  • 主线程(UI线程):这是程序启动时默认的线程,它处理用户界面用户交互。主线程不能做耗时操作,比如网络请求,否则界面会变得卡顿

  • 后台线程:用于执行耗时的操作,比如下载文件处理大数据等。后台线程不会阻塞主线程,可以让主线程继续响应用户操作

线程的主要方法

  • thread.start()启动一个新线程。当调用 thread.start() 方法时,线程会从 run() 方法开始执行

    Thread thread = new Thread(new Runnable() {
        @Override
        public void run() {
            // 这是线程要做的工作
        }
    });
    thread.start(); // 启动线程
    
  • run()定义线程要执行的代码。当线程启动时run() 方法里的代码会被执行

    new Thread(new Runnable() {
        @Override
        public void run() {
            System.out.println("线程在运行");
        }
    }).start();
    
  • thread.sleep(long millis)当前线程暂停执行指定的时间(毫秒)thread.sleep() 方法使线程暂停执行

    try {
        Thread.sleep(2000); // 休眠2秒
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    
    • 参数解析
      • millis当前线程暂停执行指定的时间(毫秒)
  • thread.join()等待当前线程完成调用 thread.join()可以等到另一个线程结束

    Thread thread = new Thread(new Runnable() {
        @Override
        public void run() {
            System.out.println("线程正在执行任务");
        }
    });
    thread.start();
    try {
        thread.join(); // 等待线程完成
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    
  • thread.interrupt()中断线程的休眠或等待状态。它会中断线程的等待或休眠状态,并引发 InterruptedException

    Thread thread = new Thread(new Runnable() {
        @Override
        public void run() {
            try {
                Thread.sleep(5000); // 休眠5秒
            } catch (InterruptedException e) {
                System.out.println("线程被中断");
            }
        }
    });
    thread.start();
    thread.interrupt(); // 中断线程
    
  • thread.isAlive()检查线程是否还在运行

    Thread thread = new Thread(new Runnable() {
        @Override
        public void run() {
            // 执行任务
        }
    });
    thread.start();
    System.out.println("线程是否还活着: " + thread.isAlive());
    
  • thread.setPriority(int priority)分配不同的任务优先级优先级高的线程优先获得CPU时间

    Thread thread = new Thread(new Runnable() {
        @Override
        public void run() {
            // 执行任务
        }
    });
    thread.setPriority(Thread.MAX_PRIORITY); // 设置最高优先级
    thread.start();
    
    • 参数解析
      • priority设置线程的优先级。通常取值为:Thread.MIN_PRIORITYThread.NORM_PRIORITYThread.MAX_PRIORITY

主要方法总结

  • 线程(Thread)是使程序可以同时执行多个任务的工具。主要方法包括:
    • start()启动线程,让它开始工作
    • run():定义线程要执行的代码
    • sleep(long millis):让线程暂停执行指定的时间
    • join()等待线程完成任务
    • interrupt()中断线程的休眠或等待状态
    • isAlive()检查线程是否还在运行
    • setPriority(int priority):设置线程的优先级

创建和使用线程

简单的线程

  • 在后台做一个简单的任务,比如打印一条消息。可以创建一个线程来完成这个任务,而不会影响到主线程

    // 创建一个新的线程
    new Thread(new Runnable() {
        // 定义了线程中要执行的任务
        @Override
        public void run() {
            // 这是在后台线程中运行的代码
            System.out.println("后台任务执行中...");
        }
    // 启动线程,线程开始执行run()方法中的代码
    }).start();
    

线程池

  • 如果有很多任务需要处理,创建和管理大量线程很麻烦线程池是一个很好的解决方案,它可以重用线程管理线程的创建和销毁

    // 创建一个线程池,最多同时运行4个线程
    ExecutorService executor = Executors.newFixedThreadPool(4);
    // 将任务提交给线程池执行
    executor.submit(new Runnable() {
        @Override
        public void run() {
            // 执行后台任务
            System.out.println("线程池中的任务执行中...");
        }
    });
    //关闭线程池,不再接受新任务
    executor.shutdown(); // 关闭线程池
    

线程与用户界面更新

  • 只有主线程可以更新用户界面。如果后台线程需要更新UI,可以使用以下方法:

    • runOnUiThread():可以在主线程中执行代码

      runOnUiThread(new Runnable() {
          @Override
          public void run() {
              // 更新用户界面
              myTextView.setText("更新了UI!");
          }
      });
      
    • Handler:用于在主线程其他线程之间传递消息和任务

      Handler handler = new Handler(Looper.getMainLooper());
      handler.post(new Runnable() {
          @Override
          public void run() {
              // 更新UI
              myTextView.setText("更新了UI!");
          }
      });
      

常见问题

  • 死锁:当两个或多个线程互相等待对方释放资源,导致所有线程无法继续运行避免死锁的方法包括避免嵌套锁定确保锁的获取顺序一致

  • 资源竞争:当多个线程同时访问共享资源而导致的冲突。使用同步机制(如 synchronized 关键字或 Lock 类)可以避免资源竞争

总结

  • 线程允许程序同时进行多个任务提高效率和用户体验

  • 使用线程可以保持应用的流畅性避免界面冻结

  • 线程池管理大量线程的有效工具

  • 线程与UI更新需要特别注意,通常使用runOnUiThread()或 Handler 来确保UI更新在主线程中进行

posted @ 2024-08-26 17:35  阿俊学JAVA  阅读(111)  评论(0编辑  收藏  举报