Java子线程和主线程交互

引言

在Java中,线程是最基本的执行单元。在多线程编程中,我们常常需要让子线程和主线程之间进行交互,以实现数据共享、任务协作等功能。本文将介绍在Java中实现子线程和主线程交互的几种常见方法,并提供示例代码来帮助读者更好地理解和应用。

1. 使用共享变量

最简单的方法是使用共享变量,在主线程和子线程之间共享数据。主线程和子线程可以通过共享变量读取和修改彼此的数据。

public class SharedVariableExample {
    public static void main(String[] args) {
        SharedVariable sharedVariable = new SharedVariable();

        Thread thread = new Thread(() -> {
            sharedVariable.setValue(42);
        });

        thread.start();

        int value = sharedVariable.getValue();
        System.out.println("Value: " + value);
    }
}

class SharedVariable {
    private int value;

    public int getValue() {
        return value;
    }

    public void setValue(int value) {
        this.value = value;
    }
}

在上面的示例代码中,主线程创建了一个共享变量sharedVariable,然后启动了一个子线程。子线程通过调用sharedVariable.setValue()方法修改了共享变量的值。主线程通过调用sharedVariable.getValue()方法读取了修改后的共享变量的值。

使用共享变量的方法简单直观,但可能存在线程安全问题。当多个线程同时对共享变量进行读写操作时,可能导致数据一致性问题。为了解决这个问题,我们可以使用锁或其他同步机制来保证线程安全。

2. 使用wait()和notify()方法

Java提供了wait()notify()方法来实现线程之间的等待和通知机制。通过调用这两个方法,主线程和子线程可以实现协作的功能。

public class WaitNotifyExample {
    public static void main(String[] args) {
        Object lock = new Object();

        Thread thread = new Thread(() -> {
            synchronized (lock) {
                try {
                    System.out.println("Child thread is waiting");
                    lock.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("Child thread is notified");
            }
        });

        thread.start();

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

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

在上面的示例代码中,主线程创建了一个锁对象lock,然后启动了一个子线程。子线程在获取到锁对象后,调用lock.wait()方法进入等待状态。主线程通过调用lock.notify()方法通知子线程。子线程接收到通知后,继续执行。

需要注意的是,wait()notify()方法必须在同步代码块中使用,即在获取到锁对象之后使用。否则,会抛出IllegalMonitorStateException异常。

3. 使用CountDownLatch

CountDownLatch是Java并发包中的一个同步工具类,可以用来协调多个线程之间的执行顺序。通过CountDownLatch,主线程可以等待子线程的完成,然后再继续执行。

import java.util.concurrent.CountDownLatch;

public class CountDownLatchExample {
    public static void main(String[] args) {
        CountDownLatch latch = new CountDownLatch(1);

        Thread thread = new Thread(() -> {
            System.out.println("Child thread is running");
            latch.countDown();
        });

        thread.start();

        try {
            System.out.println("Main thread is waiting");
            latch.await();
            System.out.println("Main thread is resumed");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

在上面的示例代码中,主线程创建了一个CountDownLatch对象,并指定计数器的初始值为1。主线程在调用latch.await()方法时进入等待状态。子线程执行完任务后,调用latch.countDown()方法来减少计数器的值。当计数器的值为0时,主线程被唤醒,继续执行。

4. 使用Future和Callable

Java提供