マルチスレッド(一):古典的な面接問題

7580 ワード

テーマの要件
プログラムを設計して、3つのスレッドA,B,Cを起動して、各スレッドは特定のアルファベットだけを印刷して、それぞれ10回印刷して、例えばAスレッドは“A”だけを印刷します.コンソールに「ABCABC...」を順番に表示する必要があります.
インプリメンテーションコード
方式1:Objectのwaitを採用して、notify方法
/**
 * Created by    on 2017/4/5.
 */
//    :  wait,notify
public class PrintABC {
    public static void main(String[] args) throws InterruptedException {
        Object A = new Object();
        Object B = new Object();
        Object C = new Object();

        //   ta      A B         A,  tb tc  。
        Thread ta = new Thread(new Print(A,B),"A");
        Thread tb = new Thread(new Print(B,C),"B");
        Thread tc = new Thread(new Print(C,A),"C");

        
        ta.start();
        Thread.sleep(1000);//            A->B->C
        tb.start();
        Thread.sleep(1000);
        tc.start();
    }
}

class Print implements Runnable{
    private Object self;
    private Object next;

    public Print(Object self, Object next) {
        this.self = self;
        this.next = next;
    }

    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            synchronized (self) {
                // synchronized (next) {}     ,next         
                synchronized (next) {
                    //                           
                    System.out.print(Thread.currentThread().getName());
                    //     ,     
                    next.notify();
                }
                //     next      next    ,   
                try {
                    //     ,    
                    if (i==9){
                        return;
                    }
                        self.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

方式2:ロックとConditionの方式を採用する
  • ロックはjavaです.util.concurrent.locksパッケージのインタフェースは、synchronizedメソッドと文を使用して得られるよりも広範なロック操作を提供し、スレッド同期問題をより優雅に処理することができます.
  • Conditionはjava 1.5に登場し,従来のObjectにおけるwait,notify法に代わってスレッド間のコラボレーションを実現するためである.Objectのwait,notifyメソッドに比べて,Conditionのawait,signalメソッドを用いてスレッド間のコラボレーションをより安全かつ効率的に実現するためである.
  • import java.util.concurrent.locks.Condition;
    import java.util.concurrent.locks.Lock;
    import java.util.concurrent.locks.ReentrantLock;
    
    /**
     * Created by    on 2017/4/5.
     */
    //    ,  ReentrantLock Condition
    public class PrintABC_Condition {
        //       ,           ,     A
        private String flag = "A";
    
        // Lock   
        private Lock lock = new ReentrantLock();
    
        //        Condition
        private Condition ca = lock.newCondition();
        private Condition cb = lock.newCondition();
        private Condition cc = lock.newCondition();
    
        private Thread a;
        private Thread b;
        private Thread c;
    
        public void printA() {
            //   
            lock.lock();
            try {
                //               ; ,  ; ,  ;
                if (!flag.equals("A")) {
                    ca.await();// objA.wait();
                }
                System.out.print(Thread.currentThread().getName());
                //    ,              
                flag = "B";
                //      Condition
                cb.signal();// objB.notify();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                lock.unlock();//    
            }
        }
    
        public void printB() {
            lock.lock();
            try {
                if (!flag.equals("B")) {
                    cb.await();
                }
                System.out.print(Thread.currentThread().getName());
                flag = "C";
                cc.signal();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        }
    
        public void printC() {
            lock.lock();
            try {
                if (!flag.equals("C")) {
                    cc.await();
                }
                System.out.print(Thread.currentThread().getName());
                flag = "A";
                ca.signal();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        }
    
        public PrintABC_Condition() {
            a = new Thread("A") {
                @Override
                public void run() {
                    super.run();
                    for (int i = 0; i < 10; i++) {
                        printA();
                    }
                }
            };
            b = new Thread("B") {
                @Override
                public void run() {
                    super.run();
                    for (int i = 0; i < 10; i++) {
                        printB();
                    }
                }
            };
            c = new Thread("C") {
                @Override
                public void run() {
                    super.run();
                    for (int i = 0; i < 10; i++) {
                        printC();
                    }
                }
            };
        }
    
        public void start(){
            a.start();
            b.start();
            c.start();
        }
    
        public static void main(String[] args) {
            new PrintABC_Condition().start();
        }
    }
    
    

    方式3:信号量Semaphoreを採用
    Semaphoreはカウントベースの信号量である.リソースが同時にアクセスできる数を制御でき、スレッドはacquire()を介してライセンスを取得し、なければ待機し、release()はライセンスを解放します.
    import java.util.concurrent.Semaphore;
    
    /**
     * Created by    on 2017/4/5.
     */
    //    ,  Semaphore
    public class PrintABC_Semaphore {
    
        public static void main(String[] args) {
            PrintABC_Semaphore exp = new PrintABC_Semaphore();
            exp.start();
        }
    
        //   A,B,C            0
        Semaphore sa = new Semaphore(0);
        Semaphore sb = new Semaphore(0);
        Semaphore sc = new Semaphore(0);
    
        public Thread a;
        public Thread b;
        public Thread c;
    
        public PrintABC_Semaphore() {
            //   A
            a = new Thread() {
                @Override
                public void run() {
                    super.run();
                    //    A    ,        C  
                    sc.release();
                    for (int i = 0; i < 10; i++) {
                        try {
                            //   C   ,  C       ,      
                            sc.acquire();
                            System.out.print("A");
                            //    ,    A   
                            sa.release();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            };
            b = new Thread() {
                @Override
                public void run() {
                    super.run();
                    for (int i = 0; i < 10; i++) {
                        try {
                            sa.acquire();
                            System.out.print("B");
                            sb.release();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            };
            c = new Thread() {
                @Override
                public void run() {
                    super.run();
                    for (int i = 0; i < 10; i++) {
                        try {
                            sb.acquire();
                            System.out.print("C");
                            sc.release();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            };
        }
    
        public void start() {
            a.start();
            b.start();
            c.start();
        }
    }
    
    

    もし文章があなたに役に立つと思ったら、フォローと好きをクリックして、支持に感謝します!