这里将线程间通信的途径分为两类:同享内存和消息传递。  
- volatile关键字的使用
 
就是利用volatile关键字的可见性,多个线程对它进行监控在其变量发生变化后执行对应线程的操作。  
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
   | class ThreadCommunication {     public static int STATE_RUN_A = 0;     public static int STATE_RUN_B = 1;     public static int STATE_RUN_C = 2;
      volatile static int state = STATE_RUN_A;     static int counter = 1;
      public static void main(String[] args) {
          Thread threadA = new Thread(new Runnable() {             @Override             public void run() {                 try {                                          Thread.sleep(3000);                 } catch (InterruptedException e) {                     e.printStackTrace();                 }                 int c = 1 << 3;                 if (state == STATE_RUN_A) {                     System.out.println("threadA is running!");                     for (int i = 0; i < c; i++) {                         if (i == 5) {                             state = STATE_RUN_B;                             break;                         }                     }                 }             }         });
          Thread threadB = new Thread(new Runnable() {             @Override             public void run() {                 while (true) {                     if (state == STATE_RUN_B) {                         System.out.println("threadB is running!");                         do {                             counter = counter << 1;                         } while (counter < 1 << 4);
                          state = STATE_RUN_C;                         break;                     }                 }             }         });
          Thread threadC = new Thread(new Runnable() {             @Override             public void run() {                 while (true) {                     if (state == STATE_RUN_C) {                         System.out.println("threadC is running!");                         do {                             counter = counter >> 1;                         } while (counter > 1);
                          System.out.println("threadC finish counter:" + counter);                         break;                     }                 }             }         });
          threadA.start();         threadB.start();         threadC.start();     } }
  | 
 

- Object.wait()\notify()
 
在线程中调用该线程锁对象是wait方法是,该线程就被放入等待队列,直到被其他线程通知notify。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
   | class ThreadCommunication {     static int counter = 1;     static Object lock = new Object();
      public static void main(String[] args) {
          Thread threadB = new Thread(new Runnable() {             @Override             public void run() {                 while (true) {                     synchronized (lock) {                         System.out.println("threadB is running!");
                          do {                             counter = counter << 1;                         } while (counter < 1 << 4);                         lock.notify();                         break;                     }                 }             }         });
          Thread threadC = new Thread(new Runnable() {             @Override             public void run() {                 while (true) {                     synchronized (lock) {                         if (counter == 1 << 4) {                             System.out.println("threadC is running!");                             do {                                 counter = counter >> 1;                             } while (counter > 1);
                              System.out.println("threadC finish counter:" + counter);                             break;                         } else {                             try {                                 lock.wait();                             } catch (InterruptedException e) {                                 e.printStackTrace();                             }                         }                     }                 }             }         });
          threadC.start();         threadB.start();     } }
  | 
 

- .join() {Thread.join}
 
当一个线程调用另外一个线程的join方法时,当前的线程就会阻塞等待被调用join方法的线程执行完毕后才能继续执行,所以join方法用来保证线程执行的顺序。  
- CountDownLatch类
 
CountDownLatch类可以使线程等待其他线程执行完毕后再执行。
通过一个计数器来实现,CountDownLatch初始化传入的count代表等待count个线程执行完毕后等待的线程才能恢复执行。一般有几个应用场景:
场景一:
有多个线程依赖其他多个线程的执行完的结果,这是等待的await,被等待的线程执行完调用coutdown然后计数器减一,直到减为0就恢复多个线程的执行;
场景二:
实现多个线程同时执行,多个线程都设置await coutdown设置为1 在主线程中调用countdown让多个线程同时执行运行。  
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
   | class ThreadCommunication {     static int counter = 1;     static CountDownLatch countDownLatch = new CountDownLatch(2);
      public static void main(String[] args) {
          Thread threadA = new Thread(new Runnable() {             @Override             public void run() {                 try {                     System.out.println("threadA await");                     countDownLatch.await();                 } catch (InterruptedException e) {                     e.printStackTrace();                 }                 System.out.println("threadA is running!");
              }         });
          Thread threadB = new Thread(new Runnable() {             @Override             public void run() {                 countDownLatch.countDown();                 System.out.println("threadB is running!");             }         });
          Thread threadC = new Thread(new Runnable() {             @Override             public void run() {                 while (true) {                     do {                         counter = counter << 1;                         System.out.println("threadC is running! counter=" + counter);
                      } while (counter < 1 << 5);
                      countDownLatch.countDown();                     break;                 }             }         });
          threadA.start();         try {             Thread.sleep(1000);         } catch (InterruptedException e) {             e.printStackTrace();         }         threadB.start();         threadC.start();     } }
  | 
 

- LockSupport类
LockSupport是JDK中用来实现线程阻塞和唤醒的工具。使用它可以在任何场合使线程阻塞,可以指定任何线程进行唤醒。
LockSupport的设计核心是“许可”,park是等待一个许可,unpark是为某一线程提供一种许可,如果某线程A调用park,那么除非另外一个线程调用unpark(A)给A一个许可,否则线程A将阻塞在park操作上。还有就是unpark可以在park前调用,也就是先提供许可,等到后面调用park时在消耗之前的许可。   
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
   | class ThreadCommunication {
      public static void main(String[] args) {
          Thread threadA = new Thread(new Runnable() {             @Override             public void run() {                 System.out.println("threadA park");                 LockSupport.park();                 System.out.println("threadA is running!");
              }         });
          Thread threadB = new Thread(new Runnable() {             @Override             public void run() {                 System.out.println("threadB park");                 LockSupport.park();                 System.out.println("threadB is running!");
                  System.out.println("threadB unpark threadA");                 LockSupport.unpark(threadA);             }         });
          threadA.start();         threadB.start();         try {             Thread.sleep(1000);         } catch (InterruptedException e) {             e.printStackTrace();         }         System.out.println("main thread unpark threadB");         LockSupport.unpark(threadB);     } }
  | 
 

     
    全文完。