除了锁,java还有一些别的方法可以控制同步:

1、JDK1.5 Exchange 两个线程互换数据

import java.util.concurrent.Exchanger;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * Exchange 2个线程之间交换数据
 */
public class ExchangeTest {

    /**
     * @param args
     */
    public static void main(String[] args) {
        ExecutorService service = Executors.newCachedThreadPool();
        final Exchanger<String> exchanger = new Exchanger<>();
        service.execute(new Runnable() {
            @Override
            public void run() {
                try {
                    String data2 = exchanger.exchange("zjw");
                    System.out.println("线程" + Thread.currentThread().getName() + "换回的数据为" + data2);
                } catch (Exception e) {
                    // TODO: handle exception
                }
            }
        });
        
        service.execute(new Runnable() {
            @Override
            public void run() {
                try {

                    String data2 = exchanger.exchange("lfw");
                    System.out.println("线程" + Thread.currentThread().getName() + "换回的数据为" + data2);
                } catch (Exception e) {
                    // TODO: handle exception
                }

            }
        });
    }
}

2、Semaphore

20个人去银行存款,但是该银行只有两个办公柜台,有空位则上去存钱,没有空位则只能去排队等待

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;

/**
 * 线程信号量Semaphore的运用
 * 
 * @author XIEHEJUN
 * 
 */
public class SemaphoreThread {
    private int a = 0;

    /**
     * 银行存钱类
     */
    class Bank {
        private int account = 100;

        public int getAccount() {
            return account;
        }

        public void save(int money) {
            account += money;
        }
    }

    /**
     * 线程执行类,每次存10块钱
     */
    class NewThread implements Runnable {
        private Bank bank;
        private Semaphore semaphore;

        public NewThread(Bank bank, Semaphore semaphore) {
            this.bank = bank;
            this.semaphore = semaphore;
        }

        @Override
        public void run() {
            int b = a++;
            if (semaphore.availablePermits() > 0) {
                System.out.println("线程" + b + "启动,进入银行,有位置立即去存钱");
            } else {
                System.out.println("线程" + b + "启动,进入银行,无位置,去排队等待等待");
            }
            try {
                semaphore.acquire();
                bank.save(10);
                System.out.println(b + "账户余额为:" + bank.getAccount());
                Thread.sleep(1000);
                System.out.println("线程" + b + "存钱完毕,离开银行");
                semaphore.release();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 建立线程,调用内部类,开始存钱
     */
    public void useThread() {
        Bank bank = new Bank();
        // 定义10个新号量
        Semaphore semaphore = new Semaphore(2);
        // 建立一个缓存线程池
        ExecutorService es = Executors.newCachedThreadPool();
        // 建立20个线程
        for (int i = 0; i < 10; i++) {
            // 执行一个线程
            es.submit(new Thread(new NewThread(bank, semaphore)));
        }
        // 关闭线程池
        es.shutdown();

        // 从信号量中获取两个许可,并且在获得许可之前,一直将线程阻塞
        semaphore.acquireUninterruptibly(2);
        System.out.println("到点了,工作人员要吃饭了");
        // 释放两个许可,并将其返回给信号量
        semaphore.release(2);
    }

    public static void main(String[] args) {
        SemaphoreThread test = new SemaphoreThread();
        test.useThread();
    }
}

3、.CyclicBarrier

通过它可以实现让一组线程等待至某个状态之后再全部同时执行。叫做回环是因为当所有等待线程都被释放以后,CyclicBarrier可以被重用。我们暂且把这个状态就叫做barrier,当调用await()方法之后,线程就处于barrier了。

CyclicBarrier cb = new CyclicBarrier(int n);// 一组线程等待至某个状态之后再全部同时执行
CyclicBarrier cb = new CyclicBarrier(int n,Runnable thread);// 一组线程等待至某个状态之后先执行thread线程,再全部同时执行其他线程
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;

/*
 * 处理同一个动作有多个线程同时执行的场景
 */
public class TestCyclicBarrier {
    public static void main(String[] args) {
        //1.得到一个CyclicBarrier实例
        CyclicBarrier cb = new CyclicBarrier(4);
        new Thread(new Fishing(cb),"1").start();
        new Thread(new Fishing(cb),"2").start();
        new Thread(new Fishing(cb),"3").start();
        new Thread(new Fishing(cb),"4").start();
    }

    static class Fishing implements Runnable{
        CyclicBarrier cb;
        public Fishing(CyclicBarrier cb) {
            this.cb = cb;
        }

        @Override
        public void run() {
            try {
                cb.await();
                System.out.println("第(" + Thread.currentThread().getName() + ")个人开始钓鱼");
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (BrokenBarrierException e) {
                e.printStackTrace();
            }
        }
    }
}

4、CountDownLatch(倒计时计数器)

所有线程执行完后,再执行某个线程

 百米赛跑,4名运动员选手到达场地等待裁判口令,裁判一声口令,选手听到后同时起跑,当所有选手到达终点,裁判进行汇总汇总排名。

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class CountdownLatchTest2 {

 public static void main(String[] args) {
 ExecutorService service = Executors. newCachedThreadPool();
final CountDownLatch cdOrder = new CountDownLatch(1);
       final CountDownLatch cdAnswer = new CountDownLatch(4);
       for (int i = 0; i < 4; i++) {
          Runnable runnable = new Runnable() {
              public void run() {
                 try {
                    System. out.println("选手" + Thread.currentThread().getName() + "正等待裁判发布口令");
                    cdOrder.await();
                    System. out.println("选手" + Thread.currentThread().getName() + "已接受裁判口令");
                    Thread. sleep((long) (Math. random() * 10000));
                    System. out.println("选手" + Thread.currentThread().getName() + "到达终点");
                    cdAnswer.countDown();
                 } catch (Exception e) {
                    e.printStackTrace();
                 }
             }
          };
          service.execute(runnable);
       }
       try {
          Thread. sleep((long) (Math. random() * 10000));

          System. out.println("裁判" + Thread.currentThread ().getName() + "即将发布口令" );
          cdOrder.countDown();
          System. out.println("裁判" + Thread.currentThread ().getName() + "已发送口令,正在等待所有选手到达终点" );
          cdAnswer.await();
          System. out.println("所有选手都到达终点" );
          System. out.println("裁判" + Thread.currentThread ().getName() + "汇总成绩排名" );
       } catch (Exception e) {
          e.printStackTrace();
       }
       service.shutdown();

   }
}