zoukankan      html  css  js  c++  java
  • multithreading coding

    分类:公共资源问题、公交车问题

    顺序:Qseater lab, bank, doctor

    【饭店】

     geust

    //yuec2 Yue Cheng
    package lab9;
    
    public abstract class Guest {
    
        int mealOrder;
        abstract void placeOrder();
    
    }
    View Code

    Group

    //yuec2 Yue Cheng
    package lab9;
    
    public class Group extends Guest {
    
        static int groupsServed;
        int mealOrder = 4;
    
        @Override
        void placeOrder() {
            groupsServed++;
        }
    
    }
    View Code

    Individual

    //yuec2 Yue Cheng
    package lab9;
    
    public class Individual extends Guest {
        //只多不少,变量也可以继承
        static int individualsServed;
        int mealOrder = 1;
    
        @Override
        void placeOrder() {
            individualsServed++;
        }
    
    }
    View Code

    DynamicDiner

    //yuec2 Yue Cheng
    package lab9;
    
    import java.util.LinkedList;
    import java.util.Queue;
    import java.util.Random;
    
    import static org.junit.Assert.assertTrue;
    
    
    public class DynamicDiner implements Runnable {
    
        Queue<Guest> guestQ = new LinkedList<>();
        DynamicKitchen kitchen = new DynamicKitchen(guestQ);
        long startTime, endTime;
        static volatile boolean dinerOpen = true;
        int maxQLength, guestsEntered;
    
        public static void main(String[] args) {
            DynamicDiner dynamicDiner = new DynamicDiner();
            dynamicDiner.startTime = System.currentTimeMillis();
            Thread t1 = new Thread(dynamicDiner.kitchen);
            t1.start();
            dynamicDiner.run();
            try {
                t1.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            dynamicDiner.printReport();
            dynamicDiner.checkAssertions();
        }
    
        @Override
        public void run() {
            //write your code here
            Random rand = new Random();
    
            while (dinerOpen) {
                //注释一下哦
                int type = rand.nextInt(2); // [0,1) -> [0,2) -> [0,1]
                Guest g;
                if (type == 0) {
                    synchronized (guestQ) {
                        g = new Individual();
                        guestQ.offer(g);
                    }
                } else {
                    synchronized (guestQ) {
                        g = new Group();
                        guestQ.offer(g);
                    }
                }
                guestsEntered += 1;
    
                if (maxQLength < guestQ.size()) {
                    maxQLength = guestQ.size();
                }
    
                int interval = rand.nextInt(30) + 1; // [0,1) -> [0, 30) -> [1, 31)
                try {
                    Thread.sleep(interval);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
    
                if (System.currentTimeMillis() > startTime + 1000) {
                    dinerOpen = false;
                }
    
            }
            //while之后更新
            endTime = System.currentTimeMillis();
        }
    
        void printReport() {
            System.out.println("-------------- Guests--------------");
            System.out.printf("%-25s%5d%n", "Total guests entered:", guestsEntered);
            System.out.printf("%-25s%5d%n", "Individuals served:", Individual.individualsServed);
            System.out.printf("%-25s%5d%n", "Groups served:", Group.groupsServed);
            System.out.printf("%-25s%5d%n", "Total guests served:", kitchen.guestsServed);
            System.out.printf("%-25s%5d%n", "Guests declined service:", guestQ.size());
            System.out.println("--------- Kitchen -----------");
            System.out.printf("%-25s%5d%n", "Meals left:", kitchen.mealStock);
            System.out.printf("%-25s%s%n", "Closing status", (kitchen.underStock) ? "Under stock" : "Overstock" );
            System.out.println("-------------- Diner -------------- ");
            System.out.printf("%-25s%5d%n", "Max Q length", maxQLength);
            System.out.printf("%-25s%,d ms%n", "Diner was open for: ", endTime - startTime);
            System.out.printf("%-25s$%,5d%n", "Income:", kitchen.income);
            System.out.println("-----------------------------------");
        }
        
        void checkAssertions() {
            //following statements will check final numbers and throw assertion error when incorrect
            assertTrue(guestsEntered == Individual.individualsServed + Group.groupsServed + guestQ.size());
            assertTrue(kitchen.guestsServed == Individual.individualsServed + Group.groupsServed);
            assertTrue((kitchen.income == (Individual.individualsServed + Group.groupsServed * 4) * kitchen.mealRate));
            if (!kitchen.underStock) assertTrue(endTime - startTime > 1000);
            if (kitchen.underStock) assertTrue(kitchen.mealStock <= 4 );
            if (endTime - startTime < 1000) assertTrue(kitchen.underStock);
        }
    }
    View Code

    DynamicKitchen

    //yuec2 Yue Cheng
    package lab9;
    
    import java.util.Queue;
    import java.util.Random;
    
    public class DynamicKitchen implements Runnable {
        
        int mealStock = 175, mealRate = 6;
        boolean underStock;
        int guestsServed, income;
        Queue<Guest> guestQ;
        
        DynamicKitchen (Queue<Guest> guestQ) {
            this.guestQ = guestQ;
        }
    
        @Override
        public void run() {
            //write your code here
            Random rand = new Random();
            Guest guestServing;
    
            while (DynamicDiner.dinerOpen && !underStock) {
    
                synchronized (guestQ) {
                    guestServing = guestQ.poll();
                }
    
                if (guestServing != null) {
                    //顺序?
                    guestServing.placeOrder();
                    guestsServed++;
                    //没说啊 只能看变量有没有被用到了
                    mealStock -= guestServing.mealOrder;
                    //忘了
                    if (guestServing instanceof Group)
                        income += mealRate * 4;
                    else
                        income += mealRate;
                } 
                //good practice
                else {
                    continue;
                }
    
                int interval = rand.nextInt(16) + 5; // [0,1) -> [0,16) -> [5, 21)
                try {
                    Thread.sleep(interval);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                //头一次见
                if (mealStock <= 4 && !underStock) {
                    underStock = true;
                    if (DynamicDiner.dinerOpen) {
                        DynamicDiner.dinerOpen = false;
                    }
                }
    
            }
        }
    }
    View Code

    //注释一下哦

    int type = rand.nextInt(2); // [0,1) -> [0,2) -> [0,1]

     

    int interval = rand.nextInt(30) + 1; // [0,1) -> [0, 30) -> [1, 31)

     

    //while之后更新

    endTime = System.currentTimeMillis();

     

    //没说啊 只能看变量有没有被用到了

    mealStock -= guestServing.mealOrder;

     

    //忘了

    if (guestServing instanceof Group)

    income += mealRate * 4;

    else

    income += mealRate;

     

    //good practice

    else {

    continue;

    }

     

    //头一次见

    if (mealStock <= 4 && !underStock) {

    underStock = true;

    if (DynamicDiner.dinerOpen) {

    DynamicDiner.dinerOpen = false;

    }

    }

     

     

    【Doctor-clinic】

    //不出结果是无限循环,此时需要检查循环条件:这次是没写count++

    //多线程很难debug?呵呵呵了,尽量吧

    clinic

    package practice_14_Doctors_Clinic;
    
    import java.util.LinkedList;
    import java.util.Queue;
    import java.util.Random;
    
    public class Clinic implements Runnable{
    
        static Queue<Patient> patientQ = new LinkedList<>();
        static int patientCount;
        static long clinicOpenTime;
        int maxPatientArrivalGap;
        
        public Clinic(int maxPatientArrivalGap) {
            this.maxPatientArrivalGap = maxPatientArrivalGap;
        }
    
        @Override
        public void run() {
            Random random = new Random();
            int sleepTime = random.nextInt(maxPatientArrivalGap);
            Clinic.clinicOpenTime = System.currentTimeMillis();
            //System.out.println("ClinicManager.maxPatientCount = " + ClinicManager.maxPatientCount);
            
            //run中:一直往Q里加(synchronized),然后sleep
            for (int i = 0; i < ClinicManager.maxPatientCount; i++) {
                synchronized (Clinic.patientQ){
                    patientQ.offer(new Patient());
                }
                //System.out.println("p.id in clinic class = " + p.id);
                //System.out.println("p.endTime in clinic class = " + p.endTime);
                try {
                    Thread.sleep(sleepTime);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }    
    }
    View Code

    doctor

    package practice_14_Doctors_Clinic;
    
    public class Doctor implements Runnable {
        int consulationTime;
    
        public Doctor(int consulationTime) {
            this.consulationTime = consulationTime;
        }
    
        @Override
        public void run() {
            //人数不足时,poll, 统计加人数,sleep
            while (Clinic.patientCount < ClinicManager.maxPatientCount) {
                // 这好像不对 Clinic.patientQ.size = 0
                Patient p;
                
                synchronized (Clinic.patientQ) {
                    p = Clinic.patientQ.poll();
                }
                //非空必须加
                if(p != null) {
                    //System.out.println("Clinic.patientQ.size in doctor = " + Clinic.patientQ.size());
                    //System.out.println("p id in doctor = " + p.id);
                    Clinic.patientCount++;
                    p.endTime = System.currentTimeMillis();
                    ClinicManager.patientWaitTime += p.endTime - p.startTime;
                }
    
                try {
                    Thread.sleep(consulationTime);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
    
        }
    
    }
    View Code

    patient

    package practice_14_Doctors_Clinic;
    
    public class Patient {
    
        static int count;
        long startTime;
        long endTime;
        int id;
        
        Patient() {
            this.startTime = System.currentTimeMillis();
            //要更新的变量,这里设置成啥?没有变量就不需要设置
    //        this.endTime = endTime;
            Patient.count++;
            this.id = count;
        }
    }
    View Code

    //要更新的变量,这里设置成啥?完成后再改,没有变量就不需要设置

    // this.endTime = endTime;

     

     

    【Qseater

    package multithreading_Qseater;
    
    public class Person {
        int id;
        //被static修饰的成员变量和成员方法独立于该类的任何对象。也就是说,它不依赖类特定的实例,被类的所有实例共享。
        static int count;
    //好像都这样
        Person() {
            id = count++;
        }
    }
    View Code
    package multithreading_Qseater;
    
    public class HotSeat implements Runnable{
        int seatedCount = 0;
    
        @Override
        public void run() {
            Person p;
            
            //好像都是数量限制
            while (seatedCount < QSeater.maxPersons) {
                
                //只同步一个Q操作
                synchronized (QSeater.personQ) {
                    p = QSeater.personQ.poll();    
                }
                
                //有人坐就sleep
                if (p != null) {
                    try {
                        Thread.sleep(QSeater.sitTime);
                        System.out.printf("Person %d sitting%n", p.id);
                        seatedCount++;
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                } else {
                    System.out.println("Queue not ready");
                } //end if
                
            } //end while
        } //end run 
    }
    View Code
    package multithreading_Qseater;
    
    import java.util.LinkedList;
    import java.util.Queue;
    import java.util.Scanner;
    
    public class QSeater implements Runnable {
        static Queue<Person> personQ = new LinkedList<>();
        static int maxPersons, sitTime; 
        int queuedCount, delay ;
        
        //run方法一样
        @Override
        public void run() {
            while (queuedCount < maxPersons)
                try {
                    synchronized (QSeater.personQ) {
                        personQ.offer(new Person());
                        queuedCount++;
                    }
                    //放也要加Delay?
                    Thread.sleep(delay);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
        }
    
        //启动2个线程
        public static void main(String[] args) {
            QSeater qs = new QSeater();
            Scanner input = new Scanner (System.in); 
            System.out.println("How many persons to seat?");
            maxPersons = input.nextInt();
            System.out.println("Enter delay (ms)");
            qs.delay = input.nextInt();
            System.out.println("How long to sit (ms)?");
            sitTime = input.nextInt();
            input.close();
            long startTime = System.currentTimeMillis();
            Thread t1 = new Thread(qs);
            Thread t2 = new Thread(new HotSeat());
            t1.start();
            t2.start();
    
            try {
                t1.join();    //wait for thread to join back
                t2.join();    //wait for thread to join back
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            long endTime = System.currentTimeMillis();
            System.out.printf("Done in %d ms!", 
                    (endTime - startTime));
            
        } //end main
    } //end QSeater
    View Code

     【TA】

    错的课程:

    package lab8;
    
    import static org.junit.Assert.assertEquals;
    import static org.junit.Assert.assertTrue;
    
    import java.util.ArrayList;
    import java.util.Collections;
    import java.util.LinkedList;
    import java.util.List;
    import java.util.Queue;
    import java.util.Scanner;
    
    public class JavaCourse implements Runnable{
        List<TA> taList = new ArrayList<>();  //list of TA objects
        static Queue<Student> studentQ = new LinkedList<>(); // queue of Student objects
        static volatile boolean allDone = false;    //indicator for JavaCourse to keep creating new Students
        int totalTAs;  //used to take user input
        List<Thread> taThreads = new ArrayList<>(); //Contains the thread objects created for each TA
        int maxQLength;        //stores the max Q length so far
        long startTime, endTime;        //start and end time of this class's run() method before printReport is invoked
    
        //do not change this method
        public static void main(String[] args) {
            JavaCourse javaCourse = new JavaCourse();
            Scanner input = new Scanner(System.in);
            System.out.println("Enter number of TAs");
            javaCourse.totalTAs = input.nextInt();
            for (int i = 1; i <= javaCourse.totalTAs; i++) {
                System.out.print("TA" + i + "		");
            }
            System.out.println("
    ------------------------------------------------------------------------------");
            input.close();
            for (int i = 0; i < javaCourse.totalTAs; i++ ) {
                TA ta = new TA();
                Thread t = new Thread(ta);
                javaCourse.taList.add(ta);
                javaCourse.taThreads.add(t);
                t.start();
            }    
            javaCourse.run();
        }
    
        @Override
        public void run() {
            //write your code here
            startTime = System.currentTimeMillis();
            while (!allDone) {
                Student s = new Student();
                boolean sIsNull = (s == null);
                System.out.println("sIsNull = " +sIsNull);
                
                synchronized(JavaCourse.studentQ) {
                    JavaCourse.studentQ.offer(s);
                }
    //放不下
                //sleep for 5 seconds
                try {
                    Thread.sleep(5);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
    
                if (studentQ.size() > maxQLength) {
                    maxQLength = studentQ.size();
                }
                System.out.println("studentQ.size() = " + studentQ.size());
    
                if (allDone) {
                    for (Thread t : taThreads) {
                        try {
                            t.join();
                        } catch (InterruptedException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        }
                    }
                    //printReport();
                }
                endTime = System.currentTimeMillis();
                TA.totalHelpTime += endTime - startTime;
                printReport();
            }
        }
    
    
        //do not change this method
        void printReport() {
            int totalHelpTime = 0;
            System.out.println("-------------------------TAs---------------------------------------");
            Collections.sort(taList);
            for (TA ta: taList) {
                System.out.printf("%s%2d %s %3d %s %3d %s%n", "TA", ta.taID, "helped", ta.studentsHelped, "students for", ta.helpTime, "min" );
                totalHelpTime += ta.helpTime;
            }
            System.out.println("------------------------Time---------------------------------------");
            System.out.printf("%-25s%5d %s%n", "Total help time: ", totalHelpTime, "min");
            System.out.printf("%-25s%5d %s%n", "Max help time", totalTAs * TA.MAX_HELP_TIME, "min");
            System.out.printf("%-25s%5d %s%n", "Total lapsed time: ", (endTime - startTime), "min");
            System.out.println("-----------------------Students------------------------------------");
            System.out.printf("%-25s%5d%n", "Total students created:", Student.totalStudentsCreated);
            System.out.printf("%-25s%5d%n", "Total students helped: ", Student.totalStudentsHelped);
            System.out.printf("%-25s%5d%n", "Max Q length: ", maxQLength);
            System.out.printf("%-25s%5d%n", "Students left in the Q: ", studentQ.size());
            System.out.println("-------------------------------------------------------------------");
    
            //following statements are to test console output numbers
            assertEquals(Student.totalStudentsCreated, studentQ.size() + Student.totalStudentsHelped);
            assertTrue(totalHelpTime >= totalTAs * TA.MAX_HELP_TIME);
            System.out.println("totalHelpTime = " + totalHelpTime);
            System.out.println("totalTAs = " + totalTAs);
            System.out.println("TA.MAX_HELP_TIME = " + TA.MAX_HELP_TIME);
            assertTrue(allDone);
        }
    }
    View Code
    //yuec2 Yue Cheng
    
    package lab8;
    
    public class TA implements Runnable, Comparable<TA>{
        int taID;
        int studentsHelped;
        int helpTime;
        static int totalHelpTime;
        static final int MAX_HELP_TIME = 120;
        static int taCount = 0;
    
        public TA() {
            //从1开始要先加再给
            taID = ++taCount;
            //taID = taCount++;
        }
    
        @Override
        public void run() {
            //write your code here
            while (helpTime < MAX_HELP_TIME && JavaCourse.allDone == false) {
                
                synchronized (JavaCourse.studentQ) {
                    Student student = JavaCourse.studentQ.poll();
                    
                    if (student != null) {
                        int questionTime = student.askQuestion();
                        studentsHelped += 1;
                        helpTime += questionTime;
                        totalHelpTime += questionTime;
                        
                        try {
                            Thread.sleep(questionTime);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        
                        System.out.println(spacer(taID) + "TA" + taID + ":Student" + student.studentID + ":" + questionTime + "min");
                    }
                }
    
                
                if (JavaCourse.allDone == false && totalHelpTime > taCount * MAX_HELP_TIME) {
                    JavaCourse.allDone = true;
                    System.out.println("******* All done flag set by TA" + taID);
                }
                
            }
        }
    
        @Override
        public int compareTo(TA o) {
            //write your code here
            if (helpTime - o.helpTime < 0)
                return 1;
            else if (helpTime - o.helpTime > 0)
                return -1;
            else
                return 0;
        }
        
        
        //do not change this method
        String spacer(int taID) {
            StringBuilder spaces = new StringBuilder();
            for (int i = 1; i < taID; i++) {
                spaces.append("		");
            }
            return spaces.toString();
        }
    }
    View Code
    //yuec2 Yue Cheng
    
    package lab8;
    
    import java.util.Random;
    
    public class Student {
    
        static int totalStudentsCreated;
        static int totalStudentsHelped;
        int studentID;
        Random random = new Random();
    
        public Student() {
            studentID = ++totalStudentsCreated;
        }
    
        int askQuestion() {
            totalStudentsHelped += 1;
            int randomNum = random.nextInt(21);
            //[0,1) -> [0,21) -> [5, 26)
            return randomNum + 5; 
        }
    }
    View Code
    //yuec2 Yue Cheng
    
    package lab8;
    
    import java.util.*;
    
    import static org.junit.Assert.assertEquals;
    import static org.junit.Assert.assertTrue;
    
    public class JavaCourse implements Runnable{
        List<TA> taList = new ArrayList<>();  //list of TA objects
        static Queue<Student> studentQ = new LinkedList<>(); // queue of Student objects
        static volatile boolean allDone = false;    //indicator for JavaCourse to keep creating new Students
        int totalTAs;  //used to take user input
        List<Thread> taThreads = new ArrayList<>(); //Contains the thread objects created for each TA
        int maxQLength;        //stores the max Q length so far
        long startTime, endTime;        //start and end time of this class's run() method before printReport is invoked
    
        //do not change this method
        public static void main(String[] args) {
            JavaCourse javaCourse = new JavaCourse();
            Scanner input = new Scanner(System.in);
            System.out.println("Enter number of TAs");
            javaCourse.totalTAs = input.nextInt();
            for (int i = 1; i <= javaCourse.totalTAs; i++) {
                System.out.print("TA" + i + "		");
            }
            System.out.println("
    ------------------------------------------------------------------------------");
            input.close();
            for (int i = 0; i < javaCourse.totalTAs; i++ ) {
                TA ta = new TA();
                Thread t = new Thread(ta);
                javaCourse.taList.add(ta);
                javaCourse.taThreads.add(t);
                t.start();
            }    
            javaCourse.run();
        }
    
        @Override
        public void run() {
            //write your code here
            startTime = System.currentTimeMillis();
            
            while (allDone == false) {
                synchronized (studentQ) {
                    Student s = new Student();
                    studentQ.offer(s);
                    
                    try {
                        int fiveSeconds = 5;
                        Thread.sleep(fiveSeconds);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    
                    if (studentQ.size() >= maxQLength) {
                        int size =  studentQ.size();
                        maxQLength = size;
                    }
                }
                
    //            try {
    //                int fiveSeconds = 5;
    //                Thread.sleep(fiveSeconds);
    //            } catch (InterruptedException e) {
    //                e.printStackTrace();
    //            }
    //            
    //            if (studentQ.size() >= maxQLength) {
    //                int size =  studentQ.size();
    //                maxQLength = size;
    //            }
            }
            
            for (int i = 0; i < taThreads.size(); i++) {
                Thread t = taThreads.get(i);
                try {
                    t.join();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            
            endTime = System.currentTimeMillis();
            printReport();
        }
        
        
        //do not change this method
        void printReport() {
            int totalHelpTime = 0;
            System.out.println("-------------------------TAs---------------------------------------");
            Collections.sort(taList);
            for (TA ta: taList) {
                System.out.printf("%s%2d %s %3d %s %3d %s%n", "TA", ta.taID, "helped", ta.studentsHelped, "students for", ta.helpTime, "min" );
                totalHelpTime += ta.helpTime;
            }
            System.out.println("------------------------Time---------------------------------------");
            System.out.printf("%-25s%5d %s%n", "Total help time: ", totalHelpTime, "min");
            System.out.printf("%-25s%5d %s%n", "Max help time", totalTAs * TA.MAX_HELP_TIME, "min");
            System.out.printf("%-25s%5d %s%n", "Total lapsed time: ", (endTime - startTime), "min");
            System.out.println("-----------------------Students------------------------------------");
            System.out.printf("%-25s%5d%n", "Total students created:", Student.totalStudentsCreated);
            System.out.printf("%-25s%5d%n", "Total students helped: ", Student.totalStudentsHelped);
            System.out.printf("%-25s%5d%n", "Max Q length: ", maxQLength);
            System.out.printf("%-25s%5d%n", "Students left in the Q: ", studentQ.size());
            System.out.println("-------------------------------------------------------------------");
            
            //following statements are to test console output numbers
            assertEquals(Student.totalStudentsCreated, studentQ.size() + Student.totalStudentsHelped);
            assertTrue( totalHelpTime >= totalTAs * TA.MAX_HELP_TIME);
            assertTrue(allDone);
        }
    }
    View Code

    //图里有横线的变量是static的

    static int taCount = 0;

     

    //居然不给constructor,要自己写。不过有提示

    TA() {

    //注意是先加后给

    taID = ++taCount;

    }

     

    //static 变量直接用就行了,不用加点

     

    //每个constructor里一般是确定ID 

        public Student() {

        studentID = ++totalStudentsCreated;

        }

     

    //就计算每个问题的时候加了一次

    TA.totalHelpTime += questionTime;

    //TA.totalHelpTime += endTime - startTime;不对啊

    //已经更新过,这里不用更新了 而且不对

    //一路打印,放不进Q的原因是变量定义不对,检查下

     

    package multithreading_NumberMaker;

    //必须有try catch, why?添加的时候都要处理异常?

    try {

    consumer.join();

    } catch (InterruptedException e) {

    // TODO Auto-generated catch block

    e.printStackTrace();

    }

  • 相关阅读:
    ffplay 一些好玩的filter
    ffmpeg加文字水印并控制水印显示时间或显示周期
    学习笔记之redux
    vue的一些常识代码规范(小小总结)
    使用computed和watch实现子组件监听父组件的变量变化
    vuex实现状态管理的具体操作
    scss使用总结
    vue的key值引发渲染错位的血案
    mp-vue实现小程序回顶操作踩坑,wx.pageScrollTo使用无效填坑
    git 的一些指令 (遇到再补充)
  • 原文地址:https://www.cnblogs.com/immiao0319/p/10048899.html
Copyright © 2011-2022 走看看