java中兩個線程交替執行打印a-z,1-26的方式


先介紹一種synchronized方式的實現:

  提到交替打印,用到synchronized,不得不提到wait和notify,當前線程打印出當前數據之后,wait之前,需要通知其他,我即將wait,你可以繼續運行了,好了,話不多說,直接上代碼:

 1 public class T02_ReentrantLock2 {
 2     
 3     synchronized void s1() {
 4         String abc = "abcdefghijklmnopqrstuvwxyz";
 5         String[] a = abc.split("");
 6             for(String value : a) {
 7                 System.out.println(value);
 8                 this.notify();
 9                 try {
10                     this.wait();
11                     Thread.sleep(100);// 防止打印速度過快導致混亂
12                 } catch (InterruptedException e) {
13                     e.printStackTrace();
14                 }
15             }
16         
17     }
18     synchronized void n1() {
19         
20             for(int i = 1; i< 27; i++) {
21                 System.out.println(i);
22                 this.notify();
23                 try {
24                     this.wait();
25                     Thread.sleep(100);// 防止打印速度過快導致混亂
26                 } catch (InterruptedException e) {
27                     e.printStackTrace();
28                 }
29             }
30             
31     }
32     
33     public static void main(String[] args) {
34         T02_ReentrantLock2 rl = new T02_ReentrantLock2();
35         Thread t1 = new Thread(rl::s1);
36         Thread t2 = new Thread(rl::n1);
37         t1.start();
38         t2.start();
39     }
40 }

  其實實現很簡單,最主要的點,就是什么時候wait,什么時候notify,正常情況下,他們是交替出現的,目的都是currentThread wait之前,喚起其他線程。

  接下來是第二種,也是稍微復雜點的方式,直接使用ReentrantLock,進一步使用Condition,Condition相當於一個容器,在一個Lock中New多少個Condition,就相當於創建了多少個等待隊列,因此,通過一個lock,兩個不同的線程,兩個Condition,可以輕松實現以上需求,需要注意的是,每次lock后需要及時unlock。

public class T01_ReentrantLock1 {

    public static boolean isInteger(String str) {
        Pattern pattern = Pattern.compile("[0-9]*");
        return pattern.matcher(str).matches();
    }

    private static Lock lock = new ReentrantLock();
    private static List<String> a = new ArrayList<String>(
            Arrays.asList("a", "1", "b", "2", "c", "3", "d", "4", "e", "5", "f", "6", "g", "7", "h", "8", "i", "9", "j",
                    "10", "k", "11", "l", "12", "m", "13", "n", "14", "o", "15", "p", "16", "q", "17", "r", "18", "s",
                    "19", "t", "20", "u", "21", "v", "22", "w", "23", "x", "24", "y", "25", "z", "26"));
    private static volatile int i = 0;

    public static void main(String[] args) {

        Condition number = lock.newCondition();
        Condition abcString = lock.newCondition();
        new Thread(() -> {
            try {
                Thread.sleep(100);
            } catch (InterruptedException e1) {
                e1.printStackTrace();
            }
            while(i < a.size()){
                lock.lock();
                try {
                    if (isInteger(a.get(i)) ) {
                        abcString.await();
                    }
                    if(i < a.size()) {
                        System.out.println(Thread.currentThread() + " : " + a.get(i));
                        i++;
                        number.signal();
                    }
                    
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    lock.unlock();
                }
            }

        }, "String").start();
        new Thread(() -> {
            try {
                Thread.sleep(100);
                while (i < a.size()) {
                    lock.lock();
                    // 必須帶條件才會相互切換,且判斷帶條件必須是同一個對象
                    if (!isInteger(a.get(i))) {
                        number.await();
                    }
                    // 必須在打印之前判斷下,是否另外一個線程i++后還小於數組,否則數組下表越界
                    if (i < a.size()) {
                        System.out.println(Thread.currentThread() + " : " + a.get(i));
                        i++;
                        abcString.signal();
                    }

                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }

        }
            , "num").start();
    }

}

第二種方式,個人感覺還存在優化的空間,歡迎大家一起進行討論。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM