• java多线程--几个多线程面试题小结


      自学了一段时间的多线程知识,尝试了做了几个编程题,发现想象中很简单的功能,自己真写起来要花费远超自己想象的功夫,知识点易学,不易用啊.

    面试题1:编写程序实现,子线程循环10次,接着主线程循环20次,接着再子线程循环10次,主线程循环20次,如此反复,循环50次.

    package com.wang.reflect;
    //编写功能类,实现子线程和主线程的功能
    class Function{
        private boolean flag=false;
        //子线程要实现的功能
        public synchronized void sub(){
            while(flag){
                try {
                    this.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
                   
            for(int i=0;i<10;i++){
                //for循环内定义子线程的功能,这里简单的假设为打印一句话,主线程同理
                System.out.println("sub"+i);
            }
            
            flag=true;
            this.notify();
        }
        //主线程要实现的功能
        public synchronized void main(){
            while(!flag){
                try {
                    this.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            for(int i=0;i<20;i++){
                System.out.println("main"+i);
            }
            
            flag=false;
            this.notify();
        }
        
    }
    
    public class Demo01 {
      
        public static void main(String[] args) {
             final Function f=new Function();
            new Thread(
                    new Runnable(){
    
                        @Override
                        public void run() {
                            for(int i=0;i<50;i++){
                                f.sub();
                            }
                        }
                    
                    }
                    ).start();
            
            for(int i=0;i<50;i++){
                f.main();
            }
        }
    }

      JDK1.5以后,出现了Lock和condition,Lock类似于synchronized功能,用来进行线程同步,Condition功能类似于Object类中的wait和notify方法,用于线程间的通信.上面的代码可以用Lock和Condition来改进,如下:

    package com.wang.reflect;
    
    import java.util.concurrent.locks.Condition;
    import java.util.concurrent.locks.Lock;
    import java.util.concurrent.locks.ReentrantLock;
    
    //编写功能类,实现子线程和主线程的功能
    class Function{
        private boolean flag=false;
        
        Lock lock=new ReentrantLock();
        Condition con=lock.newCondition();
        //子线程要实现的功能
        public  void sub(){
            lock.lock();
            try {
                
                while(flag){
                    try {
                        con.await();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                
                
                for(int i=0;i<10;i++){
                    //for循环内定义子线程的功能,这里简单的假设为打印一句话,主线程同理
                    System.out.println("sub"+i);
                }
                
                flag=true;
                con.signal();
            } finally{
                lock.unlock();
            }
        }
        //主线程要实现的功能
        public synchronized void main(){
            lock.lock();
            try {
                while (!flag) {
                    try {
                        con.await();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                for (int i = 0; i < 20; i++) {
                    System.out.println("main" + i);
                }
                flag = false;
                con.signal();
            } finally{
                lock.unlock();
            }
        }
        
    }
    
    
    public class Demo01 {
    
        
        
        public static void main(String[] args) {
             final Function f=new Function();
            new Thread(
                    new Runnable(){
    
                        @Override
                        public void run() {
                            for(int i=0;i<50;i++){
                                f.sub();
                            }
                        }
                    
                    }
                    ).start();
            
            for(int i=0;i<50;i++){
                f.main();
            }
        }
    }

    面试题2:设计四个线程,其中两个线程每次对变量i加1,另外两个线程每次对i减1.

    package com.wang.reflect;
    
    /**
     * 设计四个线程,其中两个线程每次对变量i加1,另外两个线程每次对i减1.
     * @author Administrator
     *
     */
    public class Demo02 {
    
        private int  i=0;
        public static void main(String[] args) {
            Demo02 demo=new Demo02();
            Add add = demo.new Add();
            Sub sub = demo.new Sub();
            for(int i=1;i<=2;i++){
                new Thread(add,"线程"+i).start();
                new Thread(sub,"线程"+i).start();
            }
        }
        
        
        //定义一个内部类Add,实现功能每次对i加一
        class Add implements Runnable{
    
            @Override
            public void run() {
                for(int i=0;i<10;i++){
                    addOne();
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
            
        }
        //定义一个内部类Sub,实现功能每次对i减1
        class Sub implements Runnable{
    
            @Override
            public void run() {
                for(int i=0;i<10;i++){
                subOne();
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                }
            }
            
        }
        
        public synchronized void addOne() {
            i++;
            System.out.println(Thread.currentThread().getName()+"加一的值为:"+i);
        }
        public synchronized void subOne(){
            i--;
            System.out.println(Thread.currentThread().getName()+"减一的值为:"+i);
        }
    }

    面试题3:自己编写代码,实现生产者-消费者模型功能.内容自由发挥,只需要表达思想.

      代码中,自定义一个学生类,有name和age属性,属于共享对象,生产者负责为studnet对象赋值,消费者负责打印出student对象的name和age的值,当生产者赋值完以后通知消费者来打印,消费者打印完以后,通知生产者重新设置.

    package com.wang.reflect;
    
    //学生实体类作为共享资源
    class Student {
        private String name;// 姓名
        private int age;// 年龄
        boolean flag;// 标记变量,判断当前学生对象是否已创建赋值好
    
        //生产者的功能  ,为studnet对象赋值
        public synchronized void set(String name, int age) {
    
            if (this.flag) {
                try {
                    this.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            this.name = name;
            this.age = age;
    
            this.flag = true;
            this.notify();
        }
    
        //消费者的功能,打印sutdent对象的内容
        public synchronized void get() {
            if (!this.flag) {
                try {
                    this.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
    
            System.out.println(name + ":::" + age);
    
            this.flag = false;
            this.notify();
        }
    
    }
    
    // 模拟生产者线程类
    class SetStudent implements Runnable {
    
        // 共享资源s
        private Student s;
        private int x = 0;
    
        public SetStudent(Student s) {
            this.s = s;
        }
    
        @Override
        public void run() {
            while (true) {
                if (x % 2 == 0) {
                    s.set("郭靖", 27);
                } else {
                    s.set("黄蓉", 18);
                }
                x++;
            }
        }
    
    }
    
    // 模拟消费者线程类
    class GetStudent implements Runnable {
    
        // 共享资源s
        private Student s;
    
        public GetStudent(Student s) {
            this.s = s;
        }
    
        @Override
        public void run() {
            while (true) {
                s.get();
            }
        }
    
    }
    
    // 测试类
    public class Demo03{
    
        public static void main(String[] args) {
            Student s = new Student();
    
            SetStudent ss = new SetStudent(s);
            GetStudent gs = new GetStudent(s);
    
            Thread t1 = new Thread(ss, "生产者");
            Thread t2 = new Thread(gs, "消费者");
    
            t1.start();
            t2.start();
        }
    
    }

    面试题4: 现有的程序代码模拟产生了16个日志对象,并且需要运行16秒才能打印完这些日志,请在程序中增加4个线程去调用parseLog()方法来分头打印这16个日志对象,程序只需要运行4秒即可打印完这些日志对象。

    原始代码如下:

    public class Test {
            
            public static void main(String[] args){
                
                System.out.println("begin:"+(System.currentTimeMillis()/1000));
                /*模拟处理16行日志,下面的代码产生了16个日志对象,当前代码需要运行16秒才能打印完这些日志。
                修改程序代码,开四个线程让这16个对象在4秒钟打完。
                */
                for(int i=0;i<16;i++){  //这行代码不能改动
                    final String log = ""+(i+1);//这行代码不能改动
                    {
                             Test.parseLog(log);
                    }
                }
            }
            
            //parseLog方法内部的代码不能改动
            public static void parseLog(String log){
                System.out.println(log+":"+(System.currentTimeMillis()/1000));
                
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }        
            }
            
        }

    改写代码如下:

    package com.wang.reflect;
    
    import java.util.concurrent.ArrayBlockingQueue;
    import java.util.concurrent.BlockingQueue;
    
    public class Demo03 {
        
        public static void main(String[] args){
            //定义一个线程共享的队列容器,可以使得数据由队列的一端输入,从另外一端输出
            final BlockingQueue<String> queue=new ArrayBlockingQueue<String>(16);
            for(int i=0;i<4;i++){
                new Thread(new Runnable(){
    
                    @Override
                    public void run() {
                        while(true){
                            try {
                                parseLog(queue.take());
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        }
                    }
                    
                }).start();
            }
            
            System.out.println("begin:"+(System.currentTimeMillis()/1000));
            /*模拟处理16行日志,下面的代码产生了16个日志对象,当前代码需要运行16秒才能打印完这些日志。
            修改程序代码,开四个线程让这16个对象在4秒钟打完。
            */
            for(int i=0;i<16;i++){  //这行代码不能改动
                final String log = ""+(i+1);//这行代码不能改动
                {
                         try {
                            queue.put(log);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                }
            }
        }
        
        //parseLog方法内部的代码不能改动
        public static void parseLog(String log){
            System.out.println(log+":"+(System.currentTimeMillis()/1000));
            
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }        
        }
        
    }
  • 相关阅读:
    顺序容器2(用法)
    运算符重载
    IO相关3(string流)
    IO相关2(文件输入输出)
    C语言--指针
    Java---匿名类
    Andriod开发 --插件安装、环境配置、问题集锦
    ubuntu--vim 技巧
    ubuntu--命令大全
    各浏览器userAgent汇总
  • 原文地址:https://www.cnblogs.com/fingerboy/p/5352880.html
Copyright © 2020-2023  润新知