一道谷歌的面试题

2018-07-02  本文已影响0人  Albert_Yu

题目如下
编写一个程序,程序会启动4个线程,向4个文件A,B,C,D里写入数据,每个线程只能写一个值。
线程A:只写A
线程B:只写B
线程C:只写C
线程D:只写D

4个文件A,B,C,D。

程序运行起来,4个文件的写入结果如下:
A:ABCDABCD...
B:BCDABCDA...
C:CDABCDAB...

package com.yubin.concurrent;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @Author YUBIN
 * @create 2018-07-02
 */
public class GoogleInterviewQuestions {
    public static void main(String[] args) {

        final Task task = new Task();

        /** 创建4个线程,同时启动 */
        /**
         * Thread A
         */
        new Thread(new Runnable() {

            @Override
            public void run() {
                for (int i = 0; i < 10; i++) {
                    task.outputA();
                }
            }
        }, " Thread A").start();

        /**
         * Thread B
         */
        new Thread(new Runnable() {

            @Override
            public void run() {
                for (int i = 0; i < 10; i++) {
                    task.outputB();
                }
            }
        }, "Thread B").start();

        /**
         * Thread C
         */
        new Thread(new Runnable() {

            @Override
            public void run() {
                for (int i = 0; i < 10; i++) {
                    task.outputC();
                }
            }
        }, "Thread C").start();

        /**
         * Thread D
         */
        new Thread(new Runnable() {

            @Override
            public void run() {
                for (int i = 0; i < 10; i++) {
                    task.outputD();
                }
            }
        }, "Thread D").start();
    }

    /**
     任务类
     */
    public static class Task {
        /**
         创建一个Lock锁对象
         */
        private Lock lock = new ReentrantLock();

        private BufferedWriter bw1 = null;
        private BufferedWriter bw2 = null;
        private BufferedWriter bw3 = null;
        private BufferedWriter bw4 = null;

        private int ctl = 0;

        /**
         * Condition: 线程条件
         */
        private Condition cond1 = lock.newCondition();
        private Condition cond2 = lock.newCondition();
        private Condition cond3 = lock.newCondition();
        private Condition cond4 = lock.newCondition();

        private boolean[] outputThisRound = { false, true, true, true };

        public Task() {
            try {
                // 创建4个文件对象 前提条件是这四个文件必须存在
                bw1 = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(new File("E:/A.txt"))));
                bw2 = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(new File("E:/B.txt"))));
                bw3 = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(new File("E:/C.txt"))));
                bw4 = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(new File("E:/D.txt"))));
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        public void outputA() {

            lock.lock();
            try {
                while (outputThisRound[0]) {
                    cond1.await(); //阻塞A线程
                }

                if (ctl % 4 == 0) {
                    bw1.write("A");
                    bw1.flush();
                } else if (ctl % 4 == 1) {
                    bw4.write("A");
                    bw4.flush();
                } else if (ctl % 4 == 2) {
                    bw3.write("A");
                    bw3.flush();
                } else if (ctl % 4 == 3) {
                    bw2.write("A");
                    bw2.flush();
                }

                outputThisRound[0] = true;
                outputThisRound[1] = false;

                System.out.println("outputA signal outputB!");
                cond2.signal(); //唤醒B线程
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }

        }

        public void outputB() {

            lock.lock();

            try {
                while (outputThisRound[1]) {
                    System.out.println("outputB begin to await!");
                    cond2.await();
                }

                if (ctl % 4 == 0) {
                    bw2.write("B");
                    bw2.flush();
                } else if (ctl % 4 == 1) {
                    bw1.write("B");
                    bw1.flush();
                } else if (ctl % 4 == 2) {
                    bw4.write("B");
                    bw4.flush();
                } else if (ctl % 4 == 3) {
                    bw3.write("B");
                    bw3.flush();
                }

                outputThisRound[1] = true;
                outputThisRound[2] = false;
                System.out.println("outputB signal outputC!");
                cond3.signal();
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        }

        public void outputC() {
            lock.lock();
            try {
                while (outputThisRound[2]) {
                    System.out.println("outputC begin to await!");
                    cond3.await();
                }

                if (ctl % 4 == 0) {
                    bw3.write("C");
                    bw3.flush();
                } else if (ctl % 4 == 1) {
                    bw2.write("C");
                    bw2.flush();
                } else if (ctl % 4 == 2) {
                    bw1.write("C");
                    bw1.flush();
                } else if (ctl % 4 == 3) {
                    bw4.write("C");
                    bw4.flush();
                }

                outputThisRound[2] = true;
                outputThisRound[3] = false;
                System.out.println("outputC signal outputD!");
                cond4.signal();
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        }

        public void outputD() {
            lock.lock();

            try {
                while (outputThisRound[3]) {
                    System.out.println("outputD begin to await!");
                    cond4.await();
                }

                if (ctl % 4 == 0) {
                    bw4.write("D");
                    bw4.flush();
                } else if (ctl % 4 == 1) {
                    bw3.write("D");
                    bw3.flush();
                } else if (ctl % 4 == 2) {
                    bw2.write("D");
                    bw2.flush();
                } else if (ctl % 4 == 3) {
                    bw1.write("D");
                    bw1.flush();
                }

                outputThisRound[3] = true;
                outputThisRound[0] = false;
                ctl++;
                System.out.println("outputD signal outputA!");
                cond1.signal();
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        }
    }
}

上面这个解题答案每次只会运行一个线程而且线程的执行顺序是从A-B-C-D这一的轮询顺序,没轮询完一次ctl +1,以此来对象ABCD该写入哪个文件。
总觉得这个题目不该这么解答,先记录一下,待之后改进。

上一篇 下一篇

猜你喜欢

热点阅读