本文共 7644 字,大约阅读时间需要 25 分钟。
在Java编程中,线程之间的通信是非常重要的一部分。特别是在多线程环境下,如何实现线程之间的协作和数据传递,是开发者需要解决的核心问题。以下将深入探讨Java线程通信的几种主要方法,包括锁、等待/通知机制、信号量、管道以及ThreadLocal类。
在Java中,锁是实现线程安全的基础机制。锁的概念基于对象,称为对象锁。每个对象都有一个锁,只有持有这个锁的线程才能执行同步块中保护的代码。
package chapter7;public class ObjectLock { private static Object lock = new Object(); static class ThreadA implements Runnable { @Override public void run() { synchronized (lock) { System.out.println(lock); for (int i = 0; i < 100; i++) { System.out.println("Thread A " + i); } } } } static class ThreadB implements Runnable { @Override public void run() { synchronized (lock) { System.out.println(lock); for (int i = 0; i < 100; i++) { System.out.println("Thread B " + i); } } } } public static void main(String[] args) throws InterruptedException { new Thread(new ThreadA()).start(); Thread.sleep(10); new Thread(new ThreadB()).start(); }} 在Java中,基于锁的线程通信还支持等待/通知机制。这种机制允许线程在等待某个信号时进入WAITING状态,等待其他线程的通知。
package chapter7;public class WaitAndNotify { private static Object lock = new Object(); static class ThreadA implements Runnable { @Override public void run() { synchronized (lock) { System.out.println(lock); for (int i = 0; i < 5; i++) { try { System.out.println("ThreadA: " + i); lock.notify(); lock.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } lock.notify(); } } } static class ThreadB implements Runnable { @Override public void run() { synchronized (lock) { System.out.println(lock); for (int i = 0; i < 5; i++) { try { System.out.println("ThreadB: " + i); lock.notify(); lock.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } lock.notify(); } } } public static void main(String[] args) throws InterruptedException { new Thread(new ThreadA()).start(); Thread.sleep(10); new Thread(new ThreadB()).start(); }} wait()和notify()方法,线程可以暂时释放锁,等待其他线程的通知。这种机制非常适用于多线程程序中需要协作的场景。notify(),当前线程将一直处于等待状态,直到被唤醒。Java提供了Semaphore类来实现信号量通信。信号量机制允许多个线程竞争资源,并在适当的时候允许某些线程继续执行。
package chapter7;public class MySignal { private static volatile int signal = 0; private static final Object lock = new Object(); static class ThreadA implements Runnable { @Override public void run() { while (signal < 5) { if (signal % 2 == 0) { System.out.println("ThreadA: " + signal); synchronized (lock) { signal++; } } } } } static class ThreadB implements Runnable { @Override public void run() { while (signal < 5) { if (signal % 2 == 1) { System.out.println("ThreadB: " + signal); synchronized (lock) { signal++; } } } } } public static void main(String[] args) throws InterruptedException { new Thread(new ThreadA()).start(); Thread.sleep(100); new Thread(new ThreadB()).start(); }} Semaphore类,程序可以管理资源的使用和线程的竞争。例如,上面的代码中,signal变量用来控制线程的执行顺序。管道是一种基于内存的通信机制,适用于不同线程之间的数据传输。Java提供了基于字符流和字节流的管道实现。
import java.io.IOException;import java.io.PipedReader;import java.io.PipedWriter;public class Pipe { static class ReaderThread implements Runnable { private PipedReader reader; public ReaderThread(PipedReader reader) { this.reader = reader; } @Override public void run() { System.out.println("this is reader"); int receive = 0; try { while ((receive = reader.read()) != -1) { System.print((char) receive); } } catch (IOException e) { e.printStackTrace(); } } } static class WriterThread implements Runnable { private PipedWriter writer; public WriterThread(PipedWriter writer) { this.writer = writer; } @Override public void run() { System.out.println("this is writer"); try { writer.write("test"); } catch (IOException e) { e.printStackTrace(); } finally { try { writer.close(); } catch (IOException e) { e.printStackTrace(); } } } } public static void main(String[] args) throws IOException, InterruptedException { PipedWriter writer = new PipedWriter(); PipedReader reader = new PipedReader(); writer.connect(reader); new Thread(new ReaderThread(reader)).start(); Thread.sleep(10); new Thread(new WriterThread(writer)).start(); }} PipedReader和PipedWriter基于字符流实现通信,适用于字符数据的传输。writer.connect(reader),实现了读写器之间的连接,允许数据流动。ThreadLocal类用于线程本地存储,确保每个线程都有自己的独立副本变量。这种机制特别适用于需要线程隔离的场景,如数据库连接管理。
package chapter7;public class ThreadLocalDemo { static class ThreadA implements Runnable { private ThreadLocal threadLocal; public ThreadA(ThreadLocal threadLocal) { this.threadLocal = threadLocal; } @Override public void run() { threadLocal.set("A"); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("ThreadA out: " + threadLocal + " -> content: " + threadLocal.get()); } } static class ThreadB implements Runnable { private ThreadLocal threadLocal; public ThreadB(ThreadLocal threadLocal) { this.threadLocal = threadLocal; } @Override public void run() { threadLocal.set("B"); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("ThreadB out: " + threadLocal + " -> content: " + threadLocal.get()); } } public static void main(String[] args) { ThreadLocal threadLocal = new ThreadLocal (); new Thread(new ThreadA(threadLocal)).start(); new Thread(new ThreadB(threadLocal)).start(); }} ThreadLocal对象,确保线程之间的隔离。ThreadLocal机制,避免了共享状态引发的线程安全问题。Java提供了丰富的线程通信机制,包括锁、等待/通知机制、信号量、管道和ThreadLocal类。选择合适的通信机制,能够有效地实现多线程程序的设计需求。在实际开发中,根据具体场景选择合适的方法,才能实现高效且安全的线程通信。
转载地址:http://luczz.baihongyu.com/