欢迎来到代码驿站!

JAVA代码

当前位置:首页 > 软件编程 > JAVA代码

Java并发编程线程间通讯实现过程详解

时间:2021-05-25 08:22:13|栏目:JAVA代码|点击:

在Java中线程间通讯有多种方式,我这里列出一些常用方式,并用代码的方式展示他们是如何实现的:

  • 共享变量
  • wait, notify,notifyAll(这3个方法是Object对象中的方法,且必须与synchronized关键字结合使用)
  • CyclicBarrier、CountDownLatch
  • 利用LockSupport
  • Lock/Condition机制
  • 管道,创建管道输出流PipedOutputStream和管道输入流PipedInputStream

示例一:

package com.zhi.test;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicInteger;

import org.junit.Test;

/**
 * Java多线程-线程通讯示例<br>
 * flag作为共享变量JobB执行,notify通知Job执行,CountDownLatch通知主线程执行
 * 
 * @author 张远志
 * @since 2020年5月4日21:51:24
 *
 */
public class ThreadTest2 {
  private CountDownLatch latch;
  private volatile boolean flag = true;
  private Object lock = new Object();
  private AtomicInteger num = new AtomicInteger(0);

  class JobA implements Runnable {
    @Override
    public void run() {
      synchronized (lock) {
        flag = false;
        if (num.get() != 3) {
          try {
            lock.wait(); // wait方法会释放锁
          } catch (InterruptedException e) {
          }
        }
        System.out.println("任务A收到通知,继续执行作业");
      }
      latch.countDown();
    }
  }

  class JobB implements Runnable {
    @Override
    public void run() {
      while (flag) { // 保证JobA先申请到锁

      }
      synchronized (lock) {
        for (int i = 1; i <= 5; i++) {
          try {
            Thread.sleep(1000);
          } catch (InterruptedException e) {
          }
          int a = num.incrementAndGet();
          System.out.println("任务B第" + i + "次执行,num值为:" + a);
          if (a == 3) {
            lock.notify(); // 唤醒JobB线程,notify方法不会释放锁
          }
        }
      }
      latch.countDown();
    }
  }

  @Test
  public void test() {
    latch = new CountDownLatch(2);
    new Thread(new JobA()).start();
    new Thread(new JobB()).start();
    try {
      latch.await(); // 保证2个线程都执行完毕
    } catch (InterruptedException e) {
    }
  }
}

结果输出:

任务B第1次执行,num值为:1
任务B第2次执行,num值为:2
任务B第3次执行,num值为:3
任务B第4次执行,num值为:4
任务B第5次执行,num值为:5
任务A收到通知,继续执行作业

示例二:

package com.zhi.test;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.locks.LockSupport;

import org.junit.Test;

/**
 * Java多线程-线程通讯示例,利用LockSupport
 * 
 * @author 张远志
 * @since 2020年5月4日21:51:24
 *
 */
public class ThreadTest3 {
  private CountDownLatch latch;
  private volatile int num = 0;
  private Thread ta;
  private Thread tb;

  class JobA implements Runnable {
    @Override
    public void run() {
      if (num != 3) {
        LockSupport.park();
      }
      System.out.println("任务A收到通知,继续执行作业");
      latch.countDown();
    }
  }

  class JobB implements Runnable {
    @Override
    public void run() {
      for (int i = 1; i <= 5; i++) {
        try {
          Thread.sleep(1000);
        } catch (InterruptedException e) {
        }
        num++;
        System.out.println("任务B第" + i + "次执行,num值为:" + num);
        if (num == 3) {
          LockSupport.unpark(ta); // unpark会立即激活传入线程
        }
      }
      latch.countDown();
    }
  }

  @Test
  public void test() {
    latch = new CountDownLatch(2);
    ta = new Thread(new JobA());
    tb = new Thread(new JobB());
    ta.start();
    tb.start();
    try {
      latch.await(); // 保证2个线程都执行完毕
    } catch (InterruptedException e) {
    }
  }
}

上一篇:深入浅出分析Java抽象类和接口【功能,定义,用法,区别】

栏    目:JAVA代码

下一篇:Java8中方法引用的使用详解

本文标题:Java并发编程线程间通讯实现过程详解

本文地址:http://www.codeinn.net/misctech/128513.html

推荐教程

广告投放 | 联系我们 | 版权申明

重要申明:本站所有的文章、图片、评论等,均由网友发表或上传并维护或收集自网络,属个人行为,与本站立场无关。

如果侵犯了您的权利,请与我们联系,我们将在24小时内进行处理、任何非本站因素导致的法律后果,本站均不负任何责任。

联系QQ:914707363 | 邮箱:codeinn#126.com(#换成@)

Copyright © 2020 代码驿站 版权所有