多线程间通信常用方法及简单示例(一)
温馨提示:
本文最后更新于 2024年05月15日,已超过 252 天没有更新。若文章内的图片失效(无法正常加载),请留言反馈或直接联系我。
在Java中,多线程之间通信的方式有很多,下面我们介绍几个常用通信方法并给出简单示例:
共享变量
static int sharedVariable = 0;
static void sharedVariableExample() throws InterruptedException{
Thread thread = new Thread(() -> {
for (int i = 0; i < 10; i++) {
sharedVariable++;
}
});
thread.start();
thread.join();
logger.info("主线程获取共享变量值:{}", sharedVariable);
}
上述示例中,主线程与子线程thread共享同一个变量sharedVariable,并在主线程中调用join()方法,该方法会等待子线程执行完成后继续执行,在thread线程修改了变量的值之后,主线程就可以读取到修改后的值
wait()和notify()/notifyAll()
static final Object LOCK = new Object();
static boolean flag = true;
static void notifyExample() {
new Thread(() -> {
synchronized (LOCK) {
while (flag) {
try {
LOCK.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
logger.info("线程1被唤醒并获取读取到flag属性值");
}
}).start();
new Thread(() -> {
synchronized (LOCK) {
flag = false;
LOCK.notify();
logger.info("线程2设置flag为false并唤醒线程1");
}
}).start();
}
通过Object类的wait()、notify()和notifyAll()方法实现线程间的等待和通知机制。在上述示例中线程1调用wait()方法等待线程2的唤醒,线程2通过notify()或notifyAll()方法来将其唤醒线程1继续运行
CountDownLatch
static void countDownLatchExample() throws InterruptedException {
CountDownLatch latch = new CountDownLatch(1);
new Thread(() -> {
try {
logger.info("线程1正在等待主线程释放");
latch.await();
logger.info("线程1等到主线程释放");
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
logger.info("模拟其他线程执行任务");
Thread.sleep(1000);
logger.info("任务执行完成计数器减一");
latch.countDown();
}
CountDownLatch是一种多线程同步工具,它允许一个或多个线程等待其他线程完成操作后再继续执行。它通过一个计数器设置初始线程的数量,每个线程完成任务时都将计数器减一,当计数器减为0时,所有等待的线程被唤醒继续执行
Future和CompletableFuture
static void futureExample() {
ExecutorService executor = Executors.newSingleThreadExecutor();
// 使用 Future
Future<Integer> future = executor.submit(() -> {
// 模拟耗时操作
Thread.sleep(500);
return 42;
});
logger.info("Future已提交");
try {
logger.info("获取Future的结果: {}", future.get());
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
executor.shutdown();
}
static void completableFutureExample() {
CompletableFuture<Integer> completableFuture = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
return 42;
});
logger.info("CompletableFuture已提交");
try {
logger.info("获取CompletableFuture的结果: {}", completableFuture.get());
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
通过get()方法获取异步任务的执行结果
管道
static void pipedExample() throws IOException {
PipedOutputStream outputStream = new PipedOutputStream();
PipedInputStream inputStream = new PipedInputStream(outputStream);
// 发送线程
new Thread(() -> {
try {
String message = "Hello, World!";
outputStream.write(message.getBytes());
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}).start();
// 接收线程
new Thread(() -> {
try {
byte[] buffer = new byte[1024];
int bytesRead = inputStream.read(buffer);
logger.info("接收线程读取到管道数据:{}", new String(buffer, 0, bytesRead));
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}).start();
}
管道(PipedInputStream和PipedOutputStream、PipedReader和PipedWriter)提供了一种在两个线程之间传输数据的机制。一个线程向管道中写入数据,另一个线程则从管道中读取数据,从而实现线程间通信
我们来测试以下以上方法的执行结果
每种通信方式都有其适用的场景,实际场景中需要根据具体的需求和情况选择合适的线程通信方式。下一篇我们给出更多线程间通信的方式
正文到此结束
- 本文标签: java 多线程
- 本文链接: https://www.58cto.cn/article/53
- 版权声明: 本文由程序言原创发布, 非商业性可自由转载、引用,但需署名作者且注明文章出处:程序言 》 多线程间通信常用方法及简单示例(一) - https://www.58cto.cn/article/53