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提供