《Java零基础教学》是一套深入浅出的 Java 编程入门教程。全套教程从Java基础语法开始,适合初学者快速入门,同时也从实例的角度进行了深入浅出的讲解,让初学者能够更好地理解Java编程思想和应用。
本教程内容包括数据类型与运算、流程控制、数组、函数、面向对象基础、字符串、集合、异常处理、IO 流及多线程等 Java 编程基础知识,并提供丰富的实例和练习,帮助读者巩固所学知识。本教程不仅适合初学者学习,也适合已经掌握一定 Java 基础的读者进行查漏补缺。
前言
多线程是计算机科学中非常重要的一个概念,它可以提高程序的执行效率,充分利用计算机的资源。在 Java 编程中,多线程也很常见,Java 提供了丰富的多线程库支持。但是多线程也存在一些困难,如线程间的通讯、协作等问题。本文将深入探讨如何让线程之间默契无间地通讯和协作,帮助读者更好地理解和应用 Java 多线程。
摘要
本文将介绍 Java 多线程中的线程通讯和协作技巧。首先讨论了线程通讯的基本原理,包括 wait(), notify() 和 notifyAll() 等方法的使用。然后,介绍了线程协作的概念和常见技巧,如使用 Semaphore、CountDownLatch 和 CyclicBarrier 等工具类。最后,通过代码实现多个线程之间的通讯和协作,并提供了测试用例。
线程通讯
线程通讯是指多个线程之间的信息交换和协作。在 Java 中,线程通讯主要通过共享对象的方式实现。多个线程共享一个对象,通过该对象的方法实现线程之间的通讯。
wait() 和 notify()
wait() 和 notify() 是 Java 中实现线程通讯的两个重要方法。它们都属于 Object 类,任何一个 Java 对象都可以调用这两个方法。其基本思想是在一个共享对象上进行操作,使线程挂起或唤醒。
wait() 方法的作用是使当前线程进入等待状态,直到其他线程调用了该对象的 notify() 或 notifyAll() 方法唤醒它。
java
public synchronized void wait() throws InterruptedException;
public synchronized void wait(long timeout) throws InterruptedException;
public synchronized void wait(long timeout, int nanos) throws InterruptedException;
notify() 方法的作用是唤醒一个等待该对象的线程。
java
public synchronized void notify();
notifyAll() 方法的作用是唤醒所有等待该对象的线程。
java
public synchronized void notifyAll();
代码示例
下面是一个经典的生产者-消费者模型,使用 wait() 和 notify() 方法实现线程通讯。
生产者线程:
java
class Producer implements Runnable {
private Queue<String> queue;
private int maxSize;
private int i = 0;
public Producer(Queue<String> queue, int maxSize) {
this.queue = queue;
this.maxSize = maxSize;
}
@Override
public void run() {
while (true) {
synchronized (queue) {
while (queue.size() == maxSize) { // 当队列满了,生产者线程等待
try {
queue.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
queue.offer("message" + (++i));
System.out.println("produce: " + i);
queue.notifyAll(); // 生产者线程生产完消息,唤醒所有等待队列的线程
}
}
}
}
消费者线程:
java
class Consumer implements Runnable {
private Queue<String> queue;
public Consumer(Queue<String> queue) {
this.queue = queue;
}
@Override
public void run() {
while (true) {
synchronized (queue) {
while (queue.isEmpty()) { // 当队列为空,消费者线程等待
try {
queue.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
String message = queue.poll();
System.out.println("consume: " + message);
queue.notifyAll(); // 消费者线程消费完消息,唤醒所有等待队列的线程
}
}
}
}
测试代码:
java
public static void main(String[] args) {
Queue<String> queue = new LinkedList<>();
int maxSize = 5;
Thread producerThread = new Thread(new Producer(queue, maxSize));
Thread consumerThread = new Thread(new Consumer(queue));
producerThread.start();
consumerThread.start();
}
测试结果如下:
线程协作
线程协作是指多个线程之间相互协作,共同完成一个任务。在 Java 中,线程协作主要通过工具类实现。常见的工具类有 Semaphore、CountDownLatch 和 CyclicBarrier 等。
Semaphore
Semaphore 是 Java 中一个基于计数器的同步工具类,用来控制同时访问某个资源的线程数量。它通过 acquire() 和 release() 方法来协调线程的运行。
java
public Semaphore(int permits);
public Semaphore(int permits, boolean fair);
public void acquire() throws InterruptedException;
public void acquire(int permits) throws InterruptedException;
public void release();
public void release(int permits);
其中 permits 表示资源的数量,fair 表示使用公平或非公平的机制。当 permits 大于 1 时,表示多线程可以同时访问资源。
CountDownLatch
CountDownLatch 是 Java 中一个基于计数器的同步工具类,用来协调多个线程之间的运行。它通过 await() 和 countDown() 方法来协调线程的运行。
java
public CountDownLatch(int count);
public void await() throws InterruptedException;
public boolean await(long timeout, TimeUnit unit) throws InterruptedException;
public void countDown();
public long getCount();
其中 count 表示需要完成的任务数量。当 count 减为 0 时,所有的线程将被唤醒。
CyclicBarrier
CyclicBarrier 是 Java 中一个同步工具类,用来协调多个线程之间的运行。它允许多个线程在某个屏障处阻塞,直到所有线程都到达该屏障后才能继续执行。
java
public CyclicBarrier(int parties);
public CyclicBarrier(int parties, Runnable barrierAction);
public void await() throws InterruptedException, BrokenBarrierException;
public int await(long timeout, TimeUnit unit) throws InterruptedException, BrokenBarrierException, TimeoutException;
其中 parties 表示需要等待的线程数量。当所有的线程都到达该屏障后,可以选择执行 barrierAction。当最后一个线程到达该屏障后,所有的线程将被唤醒。
代码示例
下面是一个使用 Semaphore 实现并发控制的示例。
java
class SemaphoreDemo implements Runnable {
private Semaphore semaphore;
private int n;
public SemaphoreDemo(Semaphore semaphore, int n) {
this.semaphore = semaphore;
this.n = n;
}
@Override
public void run() {
try {
semaphore.acquire(); // 获取一个 permit
for (int i = 0; i < n; i++) {
System.out.println(Thread.currentThread().getName() + ": " + i);
}
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
semaphore.release(); // 释放一个 permit
}
}
}
测试代码:
java
public static void main(String[] args) {
Semaphore semaphore = new Semaphore(2);
int n = 5;
for (int i = 0; i < 5; i++) {
new Thread(new SemaphoreDemo(semaphore, n)).start(); // 同时运行 2 个线程
}
}
测试结果如下:
小结
本文介绍了 Java 多线程中的线程通讯和协作技巧。其中,线程通讯主要通过 wait() 和 notify() 方法实现,线程协作主要通过 Semaphore、CountDownLatch 和 CyclicBarrier 等工具类实现。通过代码示例,读者可以更好地理解和应用 Java 多线程。
最后
大家如果觉得看了本文有帮助的话,麻烦给个三连(点赞、分享、转发)支持一下哈。