下面是关于“java 多线程-线程通信实例讲解”的完整攻略:
1. 为什么需要线程通信?
在多线程场景下,线程之间需要相互协作才能完成复杂的逻辑。通常情况下,线程之间的协作需要通过线程通信来实现。
在实际应用中,线程通信主要包括以下两种场景:
- 生产者和消费者模式:生产者线程负责生产数据,消费者线程负责消费数据。生产者线程需要将生产的数据传递给消费者线程,消费者线程需要从生产者线程中获取数据。
- 多线程协作模型:多个线程需要协作才能完成特定的任务。
2. 多线程-线程通信实例讲解
下面将通过两个示例来详细讲解多线程-线程通信的实现。
示例一:生产者和消费者模式
在生产者和消费者模式中,我们需要实现一个缓冲区来存储数据。生产者线程将生产的数据存放到缓冲区中,消费者线程从缓冲区中获取数据进行消费。
在本示例中,我们将定义一个缓冲区类Buffer
,该类包含以下几个方法:
put(int value)
:将一个整数值存储到缓冲区中。get()
:从缓冲区中取出一个整数值。isEmpty()
:判断缓冲区是否为空。isFull()
:判断缓冲区是否为满。
缓冲区的实现如下:
public class Buffer {
private int[] data;
private int size;
private int head;
private int tail;
private int count;
public Buffer(int size) {
this.data = new int[size];
this.size = size;
this.head = 0;
this.tail = 0;
this.count = 0;
}
public synchronized void put(int value) throws InterruptedException {
while (isFull()) {
wait();
}
data[tail++] = value;
count++;
if (tail >= size) {
tail = 0;
}
notifyAll();
}
public synchronized int get() throws InterruptedException {
while (isEmpty()) {
wait();
}
int value = data[head++];
count--;
if (head >= size) {
head = 0;
}
notifyAll();
return value;
}
public synchronized boolean isEmpty() {
return count == 0;
}
public synchronized boolean isFull() {
return count == size;
}
}
在上述代码中,我们使用synchronized
将缓冲区中的操作进行了同步。在put
方法中,我们首先使用wait
方法来阻塞生产者线程,直到缓冲区不为满。当生产者线程往缓冲区中添加数据后,需要调用notifyAll
方法来唤醒所有等待中的线程。
在get
方法中,我们同样使用了wait
方法来阻塞消费者线程,直到缓冲区不为空。当消费者线程从缓冲区中取出数据后,也需要调用notifyAll
方法来唤醒等待中的线程。
下面是一个简单的示例,通过该示例我们可以更好地理解线程通信的实现。
public class ProducerConsumerTest {
public static void main(String[] args) {
Buffer buffer = new Buffer(5);
Thread producer = new Thread(() -> {
for (int i = 1; i <= 10; i++) {
try {
buffer.put(i);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
Thread consumer = new Thread(() -> {
for (int i = 1; i <= 10; i++) {
try {
int value = buffer.get();
System.out.println("Consumer got: " + value);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
producer.start();
consumer.start();
}
}
在上述代码中,我们创建了一个缓冲区实例buffer
,并创建了一个生产者线程producer
和一个消费者线程consumer
。生产者线程会往缓冲区中添加1~10
的整数,消费者线程会从缓冲区中获取这些整数。
示例二:多线程协作模型
在多线程协作模型中,我们需要实现多个线程之间的协作。在本示例中,我们将通过一个简单的问题解决方案来演示如何实现多线程协作。
假设我们需要解决以下问题:
给定一个一维整型数组和一个整数k,找到数组中所有相邻k个元素之和的最大值。
为了解决该问题,我们可以使用多个线程来并行计算。首先,我们将数组分成k个部分,每个部分包含k个连续的元素。我们将为每个部分创建一个线程,通过线程协作来计算相邻k个元素之和的最大值。每个线程计算出其对应部分的最大值后,我们可以使用一个主线程来汇总这些结果,找到所有相邻k个元素之和的最大值。下面是实现多线程协作的代码:
public class MultiThreadedSum {
private final int[] data;
private final int k;
private final int[] results;
private int maxSum;
private final AtomicInteger finishedThreads = new AtomicInteger(0);
public MultiThreadedSum(int[] data, int k) {
this.data = data;
this.k = k;
int numThreads = data.length / k;
this.results = new int[numThreads];
}
public int getMaxSum() {
return maxSum;
}
public void compute() {
for (int i = 0; i < results.length; i++) {
int start = i * k;
int end = start + k - 1;
Runnable task = new SumTask(start, end, i);
new Thread(task).start();
}
waitForThreads();
for (int result : results) {
if (result > maxSum) {
maxSum = result;
}
}
}
private void waitForThreads() {
while (finishedThreads.get() < results.length) {
synchronized (finishedThreads) {
try {
finishedThreads.wait();
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
}
}
private void threadFinished() {
finishedThreads.incrementAndGet();
synchronized (finishedThreads) {
finishedThreads.notifyAll();
}
}
private class SumTask implements Runnable {
private final int start;
private final int end;
private final int index;
public SumTask(int start, int end, int index) {
this.start = start;
this.end = end;
this.index = index;
}
@Override
public void run() {
int sum = 0;
for (int i = start; i <= end; i++) {
sum += data[i];
}
results[index] = sum;
threadFinished();
}
}
}
在上述代码中,我们首先将数组分为k个部分,并创建了一个数组results
来存储每个部分的最大值。在compute
方法中,我们为每个部分创建一个线程,并启动线程执行相应的计算任务。在每个线程计算出其对应部分的最大值后,需要调用threadFinished
方法来告诉主线程该线程已完成计算。当所有线程都完成计算后,主线程将遍历results
数组,找到其中的最大值。
最后,我们可以使用以下代码来测试多线程协作模型的实现:
public class MultiThreadedSumTest {
public static void main(String[] args) {
int[] data = {4, 6, 8, 5, 9, 2, 4};
MultiThreadedSum mts = new MultiThreadedSum(data, 3);
mts.compute();
System.out.println("Max sum: " + mts.getMaxSum());
}
}
在上述代码中,我们创建了一个一维整型数组data
,并传入MultiThreadedSum
构造函数中。该方法将数组分为3个部分,并为每个部分创建了一个线程来并行计算相邻3个元素之和的最大值。该方法返回的最大值为32
。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:java 多线程-线程通信实例讲解 - Python技术站