美文网首页
二叉树与线程同步问题

二叉树与线程同步问题

作者: enRegan | 来源:发表于2019-07-22 16:21 被阅读0次

    某App需要从设备上下载一段录像,为提高下载速度,需要同时开启两个线程A和B,分别进行下载,并且在下载后录像片段以二叉树的形式存储,假如某一录像有10个片段,由{片段1,片段2....,片段10}组成,其下载后的存储结构如下:
    1
    /
    2 3
    / /\
    4 5 6
    \ /
    7 8 9

    10
    请实现com.regan.text.Record类,该类主要实现如下属性:

    /**
     * 模拟二叉树下载,参考https://segmentfault.com/a/1190000014743964
     *
     * @author Regan
     * @time 2019/07/19
     **/
    public class Record {
        private Record rootRecord;
        private int recordIndex;//录像片段索引
        private Record leftRecord;
        private Record rightRecord;
    
    
        public Record() {
        }
    
        public Record(Record record) {
            this.rootRecord = record;
        }
    
        public Record getRootRecord() {
            return rootRecord;
        }
    
        public void setRootRecord(Record rootRecord) {
            this.rootRecord = rootRecord;
        }
    
        public int getRecordIndex() {
            return recordIndex;
        }
    
        public void setRecordIndex(int recordIndex) {
            this.recordIndex = recordIndex;
        }
    
        public Record getLeftRecord() {
            return leftRecord;
        }
    
        public void setLeftRecord(Record leftRecord) {
            this.leftRecord = leftRecord;
        }
    
        public Record getRightRecord() {
            return rightRecord;
        }
    
        public void setRightRecord(Record rightRecord) {
            this.rightRecord = rightRecord;
        }
    private static Thread A;
        private static MyRunable ARun;
        private static Thread B;
        private static MyRunable BRun;
        private static int currentIndex = 0;
    
        /**
         * 1
         * /     \
         * 2          3
         * /            /\
         * 4          5    6
         * \       /        \
         * 7    8          9
         * \
         * 10
         * downloadRecord方法同时开启线程A和B,其中线程A下载(打印)奇数片段,线程B下载(打印)偶数片段,并使得片段按顺序输出,返回"线程名+片段索引"的列表,
         * 参数rootRecord为二叉树的根结点,在样例中指索引为1这个节点,属性recordIndex为1,如样例索引的输出结果为(A1B2A3B4A5B6A7B8A9B10)
         */
        public static String downloadRecord(final Record oldRecord, final Record newRecord) {
            if(newRecord == null){
                return "";
            }
            try {
                Thread.sleep(1000);//等一下
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            // 索引%2=1的话代表是奇数,反之也为偶数
            if (newRecord.getRecordIndex() % 2 == 1) {
                ARun = new MyRunable("A", newRecord);
                A = new Thread(ARun);
                A.start();
                if(oldRecord != null){
    //                System.out.println("A:::old:" + oldRecord.getRecordIndex() + "->new:" + newRecord.getRecordIndex());
                }
                if (newRecord.height(newRecord) == 0) {
                    A.interrupt();
                }
            } else {
                BRun = new MyRunable("B", newRecord);
                B = new Thread(BRun);
                B.start();
                if(oldRecord != null){
    //                System.out.println("A:::old:" + oldRecord.getRecordIndex() + "->new:" + newRecord.getRecordIndex());
                }
                if (newRecord.height(newRecord) == 0) {
                    B.interrupt();
                }
            }
            return "";
        }
    
    
        public static class MyRunable implements Runnable {
            private String threadName;
            private Record record;
            static private Object ob = new Object();
            public MyRunable(String threadName, Record record) {
                this.threadName = threadName;
                this.record = record;
            }
    
            public synchronized void setRecord(Record record) {
                this.record = record;
            }
    
            @Override
            public void run() {
                Random random = new Random();
                try {
                    int time = random.nextInt(10000);
                    Thread.sleep(time);//模拟下载时间
    //                    System.out.println("currentIndex : " + currentIndex + "  " +
    //                            "ThreadName:" + threadName + "   模拟下载时间  record: " + record.getRecordIndex() + "  download time: " + time);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
    //                synchronized (ob){
                if (record.getRecordIndex() - currentIndex != 1) {
                    System.out.println("currentIndex: " + currentIndex + "   还没轮到你,拦截住:" + record.getRecordIndex());
                    synchronized (ob) {
                        try {
                            ob.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        if (record.getRecordIndex() - currentIndex != 1) {
                            try {
                                ob.wait();
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        }
                        System.out.println("download done ThreadName:" + threadName + "   RecordIndex:" + record.getRecordIndex());
                        currentIndex = record.getRecordIndex();
                        if(record.getLeftRecord() != null) {
                            Record.downloadRecord(record, record.getLeftRecord());
                        }
                        if(record.getRightRecord() != null) {
                            Record.downloadRecord(record, record.getRightRecord());
                        }
                    }
                }else{
                    synchronized (ob) {
                        System.out.println("download done ThreadName:" + threadName + "   RecordIndex:" + record.getRecordIndex());
                        currentIndex = record.getRecordIndex();
                        ob.notifyAll();
                        if(record.getLeftRecord() != null) {
                            Record.downloadRecord(record, record.getLeftRecord());
                        }
                        if(record.getRightRecord() != null) {
                            Record.downloadRecord(record, record.getRightRecord());
                        }
                    }
                }
    //                }
            }
    //        }
        }
    }
    
    /**
         * 对二叉树存储的录像片段索引进行前序遍历,返回索引遍历顺序
         * */
        public static String preOrder(Record rootRecord) {
            String order = "";
            if(rootRecord != null) {
                order += rootRecord.recordIndex + " ";
                order += preOrder(rootRecord.getLeftRecord())  + " ";
                order += preOrder(rootRecord.getRightRecord())  + " ";
            }
            return order;
        }
    
       /**
         * 对二叉树存储的录像片段进行中序遍历,返回索引遍历顺序
         */
        public static String middleOrder(Record rootRecord) {
            String order = "";
            if(rootRecord != null) {
                order += middleOrder(rootRecord.getLeftRecord())  + " ";
                order += rootRecord.recordIndex + " ";
                order += middleOrder(rootRecord.getRightRecord())  + " ";
            }
            return order;
        }
    
    

    相关文章

      网友评论

          本文标题:二叉树与线程同步问题

          本文链接:https://www.haomeiwen.com/subject/vypwlctx.html