多線程輪流交替執行三種實現方法

第一種方法:採用公平鎖實現

思路及其簡單:

  1. A線程拿到鎖,執行代碼
  2. B線程拿到鎖,執行代碼
  3. A線程拿到鎖,執行代碼
  4. ......
public class FairLockDemo {

    public static void main(String[] args) {

        Runnable target = new Runnable(){

            int i = 10;

            // 利用公平鎖
            private ReentrantLock lock = new ReentrantLock(true);

            @Override
            public void run() {

                while (i >= 0) {
                    try{
                        lock.lock();
                        if(i % 2 == 0){
                            System.out.println("A");
                        }else {
                            System.out.println("B");
                        }
                        i--;
                    }finally{
                        lock.unlock();
                    }
                }
            }
        };

        Thread t1 = new Thread(target, "thread-1");
        Thread t2 = new Thread(target, "thread-2");
        t1.start();
        t2.start();
    }
}


第二種方法:採用synchronized對象鎖 + wait + notify實現

思路比較複雜,值得細細揣摩:

  • 關鍵點:每個線程都有獲得鎖的權利
  • 1、滿足if條件的,wait等待釋放鎖
  • 2、不滿足if條件的,執行業務代碼
public class TestThead {

    // 對象鎖
    private static Object obj = new Object();
    private static volatile int num = 10;

    public static void main(String[] args) {

        new Thread(new Runnable() {           // 匿名內部類
            @Override
            public void run() {
                synchronized (obj) {
                    while(num > 0){
                        if(num % 2 == 0){
                            try {
                                obj.wait();   // 釋放鎖進入等待隊列(等待池),線程2獲取到對象鎖
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        }
                        num--;
                        if(num >= 0){
                            System.out.println("B");
                        }
                        obj.notify();         // 喚醒等待隊列中線程2進入鎖池競爭對象鎖
                    }
                }
            }
        }, "thread1").start();

        new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (obj) {
                    while(num > 0){
                        if(num % 2 != 0){
                            try {
                                obj.wait();   // 釋放鎖進入等待隊列(等待池),線程1獲取到對象鎖
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        }
                        num--;
                        if(num >= 0){
                            System.out.println("A");
                        }
                        obj.notify();       // 喚醒等待隊列中線程1進入鎖池競爭對象鎖
                    }
                }
            }
        }, "thread2").start();
    }
}


3、採用Lock和Condition實現

思路:

  • 其實和上面的思路差不多
  • 只不過上面用了同一個對象鎖,思考起來比較麻煩
  • 這裏採用了兩個鎖,輪流開閉,思考起來很方便
public class LockCond {

    private static volatile int count = 10;
    private static Lock lock = new ReentrantLock();

    public static void main(String[] args) {
        Condition c1 = lock.newCondition();
        Condition c2 = lock.newCondition();

        new Thread(()->{
            while(count > 0) {
                lock.lock();
                try {
                    if(count % 2 == 0) {
                        System.out.println("A");
                        c1.await();
                    }
                    //喚醒線程2
                    c2.signal();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    count--;
                    lock.unlock();
                }
            }
        }) .start();

        new Thread(()->{
            while(count > 0) {
                lock.lock();
                try {
                    if(count % 2 == 1) {
                        System.out.println("B");
                        c2.await();
                    }
                    //喚醒線程1
                    c1.signal();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    count--;
                    lock.unlock();
                }
            }
        }) .start();
    }
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章