跳转至

Java中的wait()和Thread:深入解析与实践

简介

在Java多线程编程中,wait()Thread 是两个至关重要的概念。Thread 类是Java中线程的基础,用于创建和管理线程。而 wait() 方法则是用于线程间通信的关键机制,它允许线程暂停执行,直到其他线程调用该对象的 notify()notifyAll() 方法。深入理解这两个概念对于编写高效、可靠的多线程程序至关重要。

目录

  1. 基础概念
    • Thread类
    • wait() 方法
  2. 使用方法
    • 创建和启动线程
    • 使用wait() 进行线程通信
  3. 常见实践
    • 生产者 - 消费者模式
    • 线程同步
  4. 最佳实践
    • 避免死锁
    • 合理使用wait() 和 notify()
  5. 小结
  6. 参考资料

基础概念

Thread类

Thread 类是Java中所有线程的父类。每个线程都是 Thread 类的实例,或者是其子类的实例。通过创建 Thread 类的实例,可以定义和控制线程的行为。

public class MyThread extends Thread {
    @Override
    public void run() {
        System.out.println("This is a new thread running.");
    }
}

wait() 方法

wait() 方法是定义在 Object 类中的方法,这意味着所有Java对象都具有该方法。当一个线程调用某个对象的 wait() 方法时,该线程会释放对象的锁,并进入等待状态,直到其他线程调用该对象的 notify()notifyAll() 方法。

public class WaitExample {
    public static void main(String[] args) {
        Object lock = new Object();
        Thread thread = new Thread(() -> {
            synchronized (lock) {
                try {
                    System.out.println("Thread is about to wait.");
                    lock.wait();
                    System.out.println("Thread has been notified.");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });

        thread.start();

        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        synchronized (lock) {
            System.out.println("Main thread is notifying the waiting thread.");
            lock.notify();
        }
    }
}

使用方法

创建和启动线程

创建线程有两种常见方式:继承 Thread 类或实现 Runnable 接口。

继承Thread类

public class ThreadExample extends Thread {
    @Override
    public void run() {
        System.out.println("Thread created by extending Thread class is running.");
    }

    public static void main(String[] args) {
        ThreadExample thread = new ThreadExample();
        thread.start();
    }
}

实现Runnable接口

public class RunnableExample implements Runnable {
    @Override
    public void run() {
        System.out.println("Thread created by implementing Runnable interface is running.");
    }

    public static void main(String[] args) {
        Runnable runnable = new RunnableExample();
        Thread thread = new Thread(runnable);
        thread.start();
    }
}

使用wait() 进行线程通信

wait() 方法通常与 synchronized 块结合使用,以确保线程安全。

public class ProducerConsumer {
    private int sharedResource = 0;
    private boolean available = false;

    public synchronized void produce(int value) {
        while (available) {
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        sharedResource = value;
        available = true;
        System.out.println("Produced: " + sharedResource);
        notify();
    }

    public synchronized int consume() {
        while (!available) {
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        available = false;
        System.out.println("Consumed: " + sharedResource);
        notify();
        return sharedResource;
    }
}

常见实践

生产者 - 消费者模式

生产者 - 消费者模式是多线程编程中的经典模式,通过 wait()notify() 方法实现线程间的协作。

public class Producer implements Runnable {
    private ProducerConsumer pc;

    public Producer(ProducerConsumer pc) {
        this.pc = pc;
    }

    @Override
    public void run() {
        for (int i = 1; i <= 5; i++) {
            pc.produce(i);
        }
    }
}

public class Consumer implements Runnable {
    private ProducerConsumer pc;

    public Consumer(ProducerConsumer pc) {
        this.pc = pc;
    }

    @Override
    public void run() {
        for (int i = 1; i <= 5; i++) {
            pc.consume();
        }
    }
}

public class Main {
    public static void main(String[] args) {
        ProducerConsumer pc = new ProducerConsumer();
        Thread producerThread = new Thread(new Producer(pc));
        Thread consumerThread = new Thread(new Consumer(pc));

        producerThread.start();
        consumerThread.start();
    }
}

线程同步

wait()notify() 方法常用于实现线程同步,确保多个线程在访问共享资源时的正确性。

public class SynchronizationExample {
    private static int counter = 0;
    private static final Object lock = new Object();

    public static void increment() {
        synchronized (lock) {
            counter++;
        }
    }

    public static void main(String[] args) {
        Thread thread1 = new Thread(() -> {
            for (int i = 0; i < 1000; i++) {
                increment();
            }
        });

        Thread thread2 = new Thread(() -> {
            for (int i = 0; i < 1000; i++) {
                increment();
            }
        });

        thread1.start();
        thread2.start();

        try {
            thread1.join();
            thread2.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("Final counter value: " + counter);
    }
}

最佳实践

避免死锁

死锁是多线程编程中常见的问题,发生在两个或多个线程相互等待对方释放资源时。为避免死锁,应遵循以下原则: - 尽量减少锁的使用范围。 - 按照相同顺序获取锁。 - 避免在锁内执行长时间操作。

合理使用wait() 和 notify()

  • 使用 wait() 时,应始终在 while 循环中检查条件,以避免虚假唤醒。
  • 调用 notify()notifyAll() 时,确保线程处于正确的状态。

小结

Thread 类和 wait() 方法是Java多线程编程中的核心概念。通过合理使用它们,可以实现线程的创建、管理和通信,从而编写高效、可靠的多线程程序。在实际应用中,需要注意避免死锁等问题,并遵循最佳实践,以确保程序的正确性和性能。

参考资料