写点什么

Java 核心知识体系 - 线程管理

  • 2024-11-16
    福建
  • 本文字数:2968 字

    阅读完需:约 10 分钟

在 Java 程序开发中,线程管理是一个至关重要的方面。它涉及到如何有效地创建、调度、同步和销毁线程,以确保程序的性能、响应性和稳定性。以下是对 Java 线程管理的详细探讨。


1 线程的基本概念


线程是操作系统能够进行运算调度的最小单位,它被包含在进程之中,是进程中的实际运作单位。每个线程都有一个独立的执行路径,但共享进程的资源,如内存和文件句柄。在 Java 中,线程可以通过继承Thread类或实现Runnable接口来创建。


此外,Java 5开始,引入了java.util.concurrent包,提供了更多的并发工具,如 Callable 接口与 Future 接口,它们主要用于任务执行。


2 线程的创建与启动


2.1 继承 Thread 类


  • 创建一个类继承自Thread类。

  • 重写run()方法,该方法包含了线程要执行的任务。

  • 创建该类的对象,并调用start()方法启动线程。


class MyThread extends Thread {    public void run() {        System.out.println("线程运行中");    }}
public class ThreadDemo { public static void main(String[] args) { MyThread t = new MyThread(); t.start(); // 调用start()方法来启动线程 }}
复制代码


2.2 实现 Runnable 接口


  • 创建一个类实现Runnable接口。

  • 实现run()方法,该方法同样包含了线程要执行的任务。

  • 将该类的对象作为参数传递给Thread类的构造函数,创建Thread对象。

  • 调用Thread对象的start()方法启动线程。


class MyRunnable implements Runnable {    public void run() {        System.out.println("线程运行中");    }}
public class RunnableDemo { public static void main(String[] args) { Thread t = new Thread(new MyRunnable()); t.start(); // 调用start()方法来启动线程 }}
复制代码


3 线程的同步与通信


由于多个线程可能会同时访问共享资源,因此需要使用同步机制来确保数据的正确性和一致性。Java 提供了多种同步机制,如synchronized关键字、wait()notify()方法、以及ReentrantLock等。


3.1 synchronized 关键字


  1. 可以用于方法或代码块上,以确保同一时刻只有一个线程能够执行该方法或代码块。

  2. 当一个线程持有某个对象的锁时,其他线程将无法访问该对象的同步方法或代码块,直到锁被释放。


public class SynchronizedExample {    private int count = 0;
// 同步方法 public synchronized void increment() { count++; }
public synchronized int getCount() { return count; }
public static void main(String[] args) throws InterruptedException { SynchronizedExample example = new SynchronizedExample();
// 创建多个线程来测试同步 Thread t1 = new Thread(() -> { for (int i = 0; i < 1000; i++) { example.increment(); } });
Thread t2 = new Thread(() -> { for (int i = 0; i < 1000; i++) { example.increment(); } });
t1.start(); t2.start();
// 等待线程执行完毕 t1.join(); t2.join();
// 输出最终结果 System.out.println("Final count: " + example.getCount()); // 最终输出2000 }}
复制代码


3.2 wait()和 notify()方法


这两个方法用于在线程之间进行通信。


  1. wait()方法使当前线程等待,直到其他线程调用notify()notifyAll()方法唤醒它。

  2. notify()方法唤醒一个等待该对象的线程(如果有多个线程在等待,则选择其中一个),而notifyAll()方法唤醒所有等待该对象的线程。


点击查看大图


# 先写后读public class WaitNotifyExample {    private final Object lock = new Object();    private boolean ready = false;
public void writer() throws InterruptedException { synchronized (lock) { // 模拟写操作 Thread.sleep(1000); // 假设写操作需要1秒 System.out.println("Data is ready"); ready = true; lock.notify(); // 唤醒等待的线程 } }
public void reader() throws InterruptedException { synchronized (lock) { while (!ready) { lock.wait(); // 等待数据准备好 } // 读取数据 System.out.println("Data has been read"); } }
public static void main(String[] args) { WaitNotifyExample example = new WaitNotifyExample();
Thread writerThread = new Thread(example::writer); Thread readerThread = new Thread(example::reader);
writerThread.start(); readerThread.start(); }}
复制代码


3.3 ReentrantLock


  1. 提供了比synchronized更灵活的锁机制。

  2. 可以显式地加锁和解锁,还支持公平锁和非公平锁等特性。


四、线程的生命周期与状态


Java 线程在其生命周期中会经历多种状态,包括新建(New)、就绪(Runnable)、运行(Running)、阻塞(Blocked)、等待(Waiting)、超时等待(Timed Waiting)和终止(Terminated)。


  • 新建(New):线程被创建但尚未启动。

  • 就绪(Runnable):线程已启动且正在等待 CPU 分配时间片。

  • 运行(Running):线程正在执行其任务。

  • 阻塞(Blocked):线程因等待某个条件而暂时停止执行。

  • 等待(Waiting):线程因调用wait()方法而等待其他线程唤醒。

  • 超时等待(Timed Waiting):线程在等待某个条件的同时还设置了一个超时时间。

  • 终止(Terminated):线程已完成任务并退出。


点击查看大图


5 线程池


为了更有效地管理线程,Java 提供了线程池机制。线程池是一种用于管理和复用线程的框架,它允许开发者以较小的开销来创建和管理大量的线程。Java 中的ExecutorService接口及其实现类(如ThreadPoolExecutor)提供了强大的线程池功能。Java 中提供了几种常见的线程池类型,包括:


  1. FixedThreadPool(固定大小线程池):包含固定数量的线程,适用于需要限制并发线程数量的场景。

  2. CachedThreadPool(缓存线程池):不固定线程数量,可以根据需要自动创建新线程,适用于短期异步任务。

  3. SingleThreadPool(单线程池):只包含一个工作线程,保证所有任务按顺序执行,适用于需要保持任务顺序执行的场景。

  4. ScheduledThreadPool(定时线程池):可以执行定时任务和周期性任务。

  5. WorkStealingPool(工作窃取线程池):Java 8 中引入的一种新类型的线程池,主要用于处理耗时任务,适用于需要大量并行任务、任务之间没有依赖关系的情况。


6 最佳实践


  • 避免创建过多的线程:过多的线程会导致上下文切换频繁,从而降低系统性能。

  • 合理设置线程优先级:根据任务的紧急程度和重要性来设置线程的优先级。

  • 使用线程安全的集合:在多线程环境下使用线程安全的集合来避免数据不一致的问题。

  • 避免死锁:在设计多线程程序时要特别注意避免死锁的发生。


综上所述,Java 线程管理是一个复杂而重要的领域。通过合理地创建、调度、同步和销毁线程,可以显著提高程序的性能、响应性和稳定性。同时,开发者还需要遵循一些最佳实践来避免常见的问题和陷阱。


文章转载自:Hello-Brand

原文链接:https://www.cnblogs.com/wzh2010/p/15886703.html

体验地址:http://www.jnpfsoft.com/?from=infoq

用户头像

还未添加个人签名 2023-06-19 加入

还未添加个人简介

评论

发布
暂无评论
Java核心知识体系-线程管理_Java_不在线第一只蜗牛_InfoQ写作社区