Java Thread 类基础用法详解

一、什么是线程?为什么需要多线程?

在计算机编程中,线程是程序执行的最小单元。一个进程可以包含多个线程,它们共享进程的内存空间,但拥有各自的执行路径。想象一下,如果你只有一个线程处理任务,就像一个人同时只能做一件事;而多线程则像一个团队分工合作,能显著提高程序效率。

多线程的应用场景非常广泛:

  • 后台任务处理(如文件下载)
  • 并发请求处理(如 Web 服务器)
  • 复杂计算的并行处理
  • 界面响应与后台操作分离

二、Thread 类概述

Java 中通过java.lang.Thread类来实现线程功能。Thread 类实现了Runnable接口,包含了控制线程生命周期的各种方法。每个线程都是 Thread 类的实例,通过调用start()方法启动。

三、创建线程的两种方式

3.1 继承 Thread 类

步骤

  1. 创建 Thread 子类,重写run()方法
  2. 创建子类实例
  3. 调用start()方法启动线程

代码示例

java

// 1. 创建Thread子类
class MyThread extends Thread {
    // 重写run()方法,定义线程执行体
    @Override
    public void run() {
        for (int i = 0; i < 5; i++) {
            System.out.println("线程" + Thread.currentThread().getName() + "执行: " + i);
            try {
                // 线程休眠500毫秒
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

public class ThreadExample {
    public static void main(String[] args) {
        // 2. 创建线程实例
        MyThread thread1 = new MyThread();
        MyThread thread2 = new MyThread();
        
        // 设置线程名称
        thread1.setName("线程A");
        thread2.setName("线程B");
        
        // 3. 启动线程(不要直接调用run()方法)
        thread1.start();
        thread2.start();
        
        System.out.println("主线程执行完毕");
    }
}

3.2 实现 Runnable 接口

步骤

  1. 创建实现 Runnable 接口的类,实现run()方法
  2. 创建 Runnable 实现类的实例
  3. 将 Runnable 实例作为参数创建 Thread 对象
  4. 调用start()方法启动线程

代码示例

java

// 1. 实现Runnable接口
class MyRunnable implements Runnable {
    @Override
    public void run() {
        for (int i = 0; i < 5; i++) {
            System.out.println("线程" + Thread.currentThread().getName() + "执行: " + i);
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

public class RunnableExample {
    public static void main(String[] args) {
        // 2. 创建Runnable实例
        MyRunnable myRunnable = new MyRunnable();
        
        // 3. 创建Thread对象,传入Runnable实例
        Thread thread1 = new Thread(myRunnable, "线程C");
        Thread thread2 = new Thread(myRunnable, "线程D");
        
        // 4. 启动线程
        thread1.start();
        thread2.start();
        
        System.out.println("主线程执行完毕");
    }
}

两种方式的对比

继承 Thread 方式 实现 Runnable 方式
优点:代码简单,直接使用 this 获取线程 优点:避免单继承限制,适合多个线程共享资源
缺点:无法继承其他类 缺点:代码稍复杂,需要通过 Thread.currentThread () 获取线程

推荐使用实现 Runnable 接口的方式,因为它更灵活,且符合面向接口编程的思想。

四、Thread 类常用方法

4.1 线程启动与执行

  • start():启动线程,JVM 会调用 run () 方法
  • run():线程执行体,包含线程要执行的代码

⚠️ 注意:不要直接调用 run () 方法,这会像调用普通方法一样在当前线程执行,不会启动新线程。

4.2 线程控制方法

  • sleep(long millis):使当前线程休眠指定毫秒数
  • join():等待该线程执行完毕后再继续执行其他线程
  • interrupt():中断线程(设置中断标志,需配合 isInterrupted () 使用)
  • setPriority(int newPriority):设置线程优先级(1-10,默认为 5)
  • setDaemon(boolean on):设置为守护线程(当所有非守护线程结束时,守护线程自动结束)

sleep () 示例

java

public class SleepExample {
    public static void main(String[] args) {
        Thread thread = new Thread(() -> {
            for (int i = 0; i < 3; i++) {
                System.out.println("当前时间: " + System.currentTimeMillis());
                try {
                    Thread.sleep(1000); // 休眠1秒
                } catch (InterruptedException e) {
                    return; // 捕获中断异常,退出线程
                }
            }
        });
        thread.start();
    }
}

join () 示例

java

public class JoinExample {
    public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(() -> {
            for (int i = 0; i < 3; i++) {
                System.out.println("子线程执行中: " + i);
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        
        thread.start();
        System.out.println("等待子线程完成...");
        thread.join(); // 等待子线程执行完毕
        System.out.println("子线程已完成,主线程继续执行");
    }
}

4.3 线程状态查询方法

  • isAlive():判断线程是否处于活动状态
  • getState():获取线程状态(NEW, RUNNABLE, BLOCKED, WAITING, TIMED_WAITING, TERMINATED)
  • currentThread():获取当前正在执行的线程对象

五、线程生命周期

线程从创建到销毁经历以下状态:

  1. 新建状态 (NEW):创建 Thread 对象但未调用 start ()
  2. 就绪状态 (RUNNABLE):调用 start () 后,等待 CPU 调度
  3. 运行状态 (RUNNING):获得 CPU 资源,执行 run () 方法
  4. 阻塞状态 (BLOCKED):因某种原因暂停执行(如等待锁、I/O 操作)
  5. 等待状态 (WAITING/TIMED_WAITING):调用 wait ()/join ()/sleep () 进入等待
  6. 终止状态 (TERMINATED):run () 方法执行完毕或因异常退出

六、线程安全基础

当多个线程访问共享资源时,可能会出现数据不一致的问题。例如:

java

class Counter {
    private int count = 0;
    
    // 非线程安全的方法
    public void increment() {
        count++; // 不是原子操作,可能导致线程安全问题
    }
    
    public int getCount() {
        return count;
    }
}

public class ThreadSafetyExample {
    public static void main(String[] args) throws InterruptedException {
        Counter counter = new Counter();
        
        // 创建10个线程,每个线程自增1000次
        Runnable task = () -> {
            for (int i = 0; i < 1000; i++) {
                counter.increment();
            }
        };
        
        Thread[] threads = new Thread[10];
        for (int i = 0; i < 10; i++) {
            threads[i] = new Thread(task);
            threads[i].start();
        }
        
        // 等待所有线程完成
        for (Thread thread : threads) {
            thread.join();
        }
        
        System.out.println("预期结果: 10000");
        System.out.println("实际结果: " + counter.getCount()); // 可能小于10000
    }
}

解决线程安全问题的简单方法是使用synchronized关键字:

java

// 线程安全的方法
public synchronized void increment() {
    count++;
}

七、使用 Thread 类的注意事项

  1. 避免创建过多线程:线程创建和销毁有开销,可使用线程池
  2. 正确处理中断:使用 interrupt () 而非 stop ()(已废弃)来中断线程
  3. 释放资源:在 finally 块中释放文件句柄、网络连接等资源
  4. 避免线程饥饿:合理设置线程优先级,避免低优先级线程长期得不到执行
  5. 谨慎使用 suspend () 和 resume ():这两个方法已废弃,可能导致死锁

八、总结与进阶学习

Thread 类是 Java 多线程编程的基础,掌握它对于编写高效并发程序至关重要。本文介绍了:

  • 线程的基本概念和作用
  • 创建线程的两种方式及对比
  • Thread 类的常用方法和示例
  • 线程生命周期和状态转换
  • 线程安全基础和 synchronized 关键字
  • 使用注意事项和最佳实践

进阶学习方向

  • 线程池(ExecutorService)
  • 并发集合(ConcurrentHashMap, CopyOnWriteArrayList)
  • 锁机制(ReentrantLock, ReadWriteLock)
  • 条件变量(Condition)
  • 原子类(AtomicInteger, AtomicReference)
  • 线程间通信(wait (), notify (), notifyAll ())

建议结合 Java 官方文档和实际项目练习,深入理解多线程编程的精髓。

祝大家学习愉快,编程之路越走越宽!

你可能感兴趣的:(java,开发语言)