java的多线程通信有Lock,wait/notify,Semaphore三种方式,以一道常见面试题来简单演示这三种多线程通信方式。
两个线程循环间隔打印指定内容,一个打印从1到52的数字,一个打印从A到Z的字母,打印输出如下:
1
2
A
3
4
B
......
51
52
Z
使用Lock实现代码如下:
[java] view plain copy
- import java.util.concurrent.ExecutorService;
- import java.util.concurrent.Executors;
- import java.util.concurrent.locks.Condition;
- import java.util.concurrent.locks.Lock;
- import java.util.concurrent.locks.ReentrantLock;
- public class ThreadCommunicationTest {
- private final Lock lock = new ReentrantLock();
- private final Condition conditionA = lock.newCondition();
- private final Condition conditionB = lock.newCondition();
- private static char currentThread = 'A';
- public static void main(String[] args) {
- ThreadCommunicationTest test = new ThreadCommunicationTest();
- ExecutorService service = Executors.newCachedThreadPool();
- service.execute(test.new RunnableA());
- service.execute(test.new RunnableB());
- service.shutdown();
- }
- private class RunnableA implements Runnable {
- public void run() {
- for (int i = 1; i <= 52; i++) {
- lock.lock();
- try {
- while (currentThread != 'A') {
- try {
- conditionA.await();
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- System.out.println(i);
- if (i % 2 == 0) {
- currentThread = 'B';
- conditionB.signal();
- }
- } finally {
- lock.unlock();
- }
- }
- }
- }
- private class RunnableB implements Runnable {
- public void run() {
- for (char c = 'A'; c <= 'Z'; c++) {
- lock.lock();
- try {
- while (currentThread != 'B') {
- try {
- conditionB.await();
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- System.out.println(c);
- currentThread = 'A';
- conditionA.signal();
- } finally {
- lock.unlock();
- }
- }
- }
- }
- }
[java] view plain copy
- import java.util.concurrent.ExecutorService;
- import java.util.concurrent.Executors;
- public class ThreadCommunicationTest2 {
- private static char currentThread = 'A';
- private final Object t = new Object(); //使用一个同步对象保证两个线程之间每一时刻只有一个线程工作
- public static void main(String[] args) {
- ThreadCommunicationTest2 test = new ThreadCommunicationTest2();
- ExecutorService service = Executors.newCachedThreadPool();
- service.execute(test.new RunnableA());
- service.execute(test.new RunnableB());
- service.shutdown();
- }
- private class RunnableA implements Runnable {
- public void run() {
- for (int i = 1; i <= 52; i++) {
- synchronized (t) {
- if(currentThread != 'A'){
- try {
- t.wait();
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- System.out.println(i);
- if (i % 2 == 0) {
- currentThread = 'B';
- t.notifyAll();
- }
- }
- }
- }
- }
- private class RunnableB implements Runnable {
- public void run() {
- for (char c = 'A'; c <= 'Z'; c++) {
- synchronized (t) {
- if(currentThread != 'B'){
- try {
- t.wait();
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- System.out.println(c);
- currentThread = 'A';
- t.notifyAll();
- }
- }
- }
- }
- }
[java] view plain copy
- import java.util.concurrent.ExecutorService;
- import java.util.concurrent.Executors;
- import java.util.concurrent.Semaphore;
- public class ThreadCommunicationTest3 {
- private final Semaphore semap = new Semaphore(1);//创建一个只有1个许可的信号量,保证两个线程间每一时刻只有一个在工作
- private static char currentThread = 'A';
- public static void main(String[] args) {
- ThreadCommunicationTest3 test = new ThreadCommunicationTest3();
- ExecutorService service = Executors.newCachedThreadPool();
- service.execute(test.new RunnableA());
- service.execute(test.new RunnableB());
- service.shutdown();
- }
- private class RunnableA implements Runnable {
- public void run() {
- for (int i = 1; i <= 52; i++) {
- try {
- semap.acquire();
- while (currentThread != 'A') {
- semap.release();
- }
- System.out.println(i);
- if (i % 2 == 0) {
- currentThread = 'B';
- }
- } catch (Exception e) {
- e.printStackTrace();
- } finally {
- semap.release();
- }
- }
- }
- }
- private class RunnableB implements Runnable {
- public void run() {
- for (char c = 'A'; c <= 'Z'; c++) {
- try {
- semap.acquire();
- while (currentThread != 'B') {
- semap.release();
- }
- System.out.println(c);
- currentThread = 'A';
- } catch (Exception e) {
- e.printStackTrace();
- } finally {
- semap.release();
- }
- }
- }
- }
- }