Day486&487&488.尚硅谷之高频重点面试题② -面经

Posted 阿昌喜欢吃黄桃

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Day486&487&488.尚硅谷之高频重点面试题② -面经相关的知识,希望对你有一定的参考价值。

高频重点面试题②

一、说说锁

  • 公平锁

    • 每个线程获取锁的时候,会根据维护的等待队列去一个一个按次序获取锁
    • 吞吐量大
  • 非公平锁

    • 并不会根据声明的顺序去严格按照顺序获取锁,会“插队”,尝试失败就会再采用类似公平锁机制

    • 会出现饥饿等情况

  • 可重入锁(递归锁)

    锁里套锁,直接获取锁内锁的锁

    • 避免了死锁

  • 自旋锁

    尝试获取锁的线程不会立刻阻塞,而是采用循环的方式去获取锁,通过循环代替阻塞

    • 减少线程上下文切换
    • 消耗CPU资源
    • 手写自旋锁

  • 写锁(独占锁)

    只能被一个线程所持有

  • 读锁(共享锁)

    可被多个线程所持有


二、CountDownLatch/CyclicBarrier/Semaphore使用过吗?

https://achang.blog.csdn.net/article/details/117935179

  • CountDownLatch倒计时门栓

    倒数count为0后,执行await()方法阻塞的线程就发车

    所有人出了门,保安才锁门

  • CyclicBarrier循环栅栏

    满足数量条件,就发车

    人到齐了,就开会

  • Semaphore信号量

    “许可证”,数量有限


三、阻塞队列知道吗?

之前的学习笔记

  • 为什么用?有什么好处?

  • 知道哪些实现类吗?

  • API

  • 手写传统版生产者消费者模式
/******
 @author 阿昌
 @create 2021-05-22 20:58
 *******
 *  用wait/notify来实现 生产者消费者模式
 */
public class ProducerConsumerModel 
    //主函数
    public static void main(String[] args) 
        EventStorage eventStorage = new EventStorage();
        Consumer1 consumer = new Consumer1(eventStorage);
        Producer1 producer = new Producer1(eventStorage);

        Thread threadConsumer = new Thread(consumer);
        Thread threadProducer = new Thread(producer);

        threadConsumer.start();
        threadProducer.start();
    


//生产者
class Producer1 implements Runnable
    private EventStorage storage;

    public Producer1(EventStorage storage) 
        this.storage = storage;
    

    @Override
    public void run() 
        for (int i = 0; i < 100; i++) 
            storage.put();
        
    


//消费者
class Consumer1 implements Runnable
    private EventStorage storage;

    public Consumer1(EventStorage storage) 
        this.storage = storage;
    

    @Override
    public void run() 
        for (int i = 0; i < 100; i++) 
            storage.take();
        
    


//队列
class EventStorage
    private int maxSize;
    private LinkedList storage;

    public EventStorage()
        this.maxSize=10;
        storage = new LinkedList<>();
    

    //生成产品
    public synchronized void put()
        //如果满了
        while (storage.size()==maxSize)
            try 
                wait();
             catch (InterruptedException e) 
                e.printStackTrace();
            
        

        //如果没满
        storage.add(new Date());
        System.out.println("生产者生产了产品,仓库里有了"+storage.size()+"个产品");
        notify();
    

    //消费产品
    public synchronized void take()
        //如果空了
        while (storage.size()<=0)
            try 
                wait();
             catch (InterruptedException e) 
                e.printStackTrace();
            
        
        //如果没空
        System.out.println("消费者消费了产品,拿到了"+storage.poll()+",现在仓库还剩下"+storage.size());
        notify();
    

  • 生产者消费者模式阻塞队列版
public class ConsumerProducer 
    static class MySource
        private volatile boolean flag = true;
        private BlockingQueue<String> blockingQueue;
        private AtomicInteger atomicInteger = new AtomicInteger();
        public MySource(BlockingQueue<String> queue)
        
            this.blockingQueue = queue;
        
        public void prod() throws InterruptedException 
            String data = null;
            while (flag)
                data = atomicInteger.incrementAndGet()+"";
                if (blockingQueue.offer(data,2L, TimeUnit.SECONDS))
                    System.out.println("生产对象,并插入对类");
                
                Thread.sleep(1000);
            
            this.flag = false;
            System.out.println("flag=false,停止生产...");
        

        public void consume() throws InterruptedException 
            while (flag)
                String data = blockingQueue.poll(2L, TimeUnit.SECONDS);
                if (data != null || null != "") 
                    System.out.println("消费对象:"+data);
                else 
                    this.flag = false;
                    System.out.println("消费者停止消费");
                
                Thread.sleep(1000);
            
        
        public void clear()
            this.flag = false;
        
    

    
    public static void main(String[] args) throws InterruptedException 
        ArrayBlockingQueue<String> queue = new ArrayBlockingQueue<String>(10);
        MySource mySource = new MySource(queue);
        new Thread(new Runnable() 
            @Override
            public void run() 

                try 
                    mySource.prod();
                 catch (InterruptedException e) 
                    e.printStackTrace();
                
            
        ).start();

        new Thread(new Runnable() 
            @Override
            public void run() 
                try 
                    mySource.consume();
                 catch (InterruptedException e) 
                    e.printStackTrace();
                
            
        ).start();

        Thread.sleep(3000L);
        System.out.println("主线程停止操作");
        mySource.clear();
    


  • Synchronized和Lock有什么区别?


四、线程池用过吗?谈谈你的理解

https://achang.blog.csdn.net/article/details/117606362

  • 为什么需要使用线程池

    • 反复创建线程开销大
    • 过多的线程会导致内存消耗
  • 线程池的好处

    • 加快响应速度
    • 便于线程的管理控制,方便数据统计
    • 合理利用CPU和内存
  • 线程池构造函数的参数

  • 流程图

  • 是否需要增加线程的判断

    • corePoolSzie
    • workQueue
    • maxPoolSize
  • 说说线程池底层原理----也就是线程池创建7大参数

  • 线程池的拒绝策略,请你谈谈

  • 为什么工作中尽量不使用Executors去创建线程池?

  • 线程池合理配置数
    • CPU密集型
      • CPU核数*2
    • IO型
      • CPU核数/ 1 * 0.9


五、谈一谈死锁

https://achang.blog.csdn.net/article/details/117431165

  • 死锁简单的定位方式可通过
    • jstack xxx + jps

以上是关于Day486&487&488.尚硅谷之高频重点面试题② -面经的主要内容,如果未能解决你的问题,请参考以下文章

Day486.尚硅谷之高频重点面试题② -面经

leetcode486 Predict the Winner

[Android开发学习] day07 &amp; day08

参考手册目录__第三部分

.~day06-07_FlinkTable&SQL

day11-StringBuilder&Math&Arrays&包装类&日期时间类