java面經查缺補漏之三十六天(前天面試完美團,不知道是否涼涼,今天主要學生產者消費者模型)

1.手寫一個生產者消費者模型?

參考:https://blog.csdn.net/u010983881/article/details/78554671?depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-4&utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-4

查了一下,這篇講的是最好的!一共有三種方式,阻塞隊列,synchronized的,lock的

最簡單的一個,基於阻塞隊列的:

import java.util.Random;
import java.util.concurrent.LinkedBlockingQueue;

public class producerByBq {
    private static final int CAPACITY = 5;
    public static void main(String[] args)
    {
        LinkedBlockingQueue<Integer> blockingQueue = new LinkedBlockingQueue<Integer>(CAPACITY);
        Thread producer1 = new producer("P-1", blockingQueue);
        Thread producer2 = new producer("P-2", blockingQueue);
        Thread consumer1 = new consumer("C1", blockingQueue);
        Thread consumer2 = new consumer("C2", blockingQueue);
        Thread consumer3 = new consumer("C3", blockingQueue);
        producer1.start();
        producer2.start();
        consumer1.start();
        consumer2.start();
        consumer3.start();
    }
    public static class producer extends Thread
    {
        private LinkedBlockingQueue<Integer> blockingQueue;
        private String name;
        private int i=0;
        public producer(String name,LinkedBlockingQueue<Integer> blockingQueue)
        {
            //這個supername是幹什麼的
            super(name);
            this.blockingQueue=blockingQueue;
            this.name=name;
        }
        public void run()
        {
            while(true)
            {
                try {
                    blockingQueue.put(i);
                    System.out.println("[" + name + "] Producing value : +" + i);
                    i++;
                    Thread.sleep(new Random().nextInt(1000));
                }catch (Exception e)
                {
                    e.printStackTrace();
                }
            }
        }

    }
    public static class consumer extends Thread
    {
        private LinkedBlockingQueue<Integer> blockingQueue;
        private String name;
        public consumer(String name,LinkedBlockingQueue<Integer> blockingQueue)
        {
            super(name);
            this.blockingQueue=blockingQueue;
            this.name=name;
        }
        public void run()
        {
            while(true)
            {
                try {
                    int x=blockingQueue.take();
                    System.out.println("[" + name + "] Consuming : " + x);
                    Thread.sleep(new Random().nextInt(1000));
                }catch (Exception e)
                {
                    e.printStackTrace();
                }
            }
        }
    }
}

第二個,基於synchronized的

import java.util.LinkedList;
import java.util.Queue;
import java.util.Random;

public class producerBySyn {
    private static final int CAPACITY = 5;
    public static void main(String[] args)
    {
        Queue<Integer> queue = new LinkedList<Integer>();
        Thread producer1 = new producer("P-1", queue,CAPACITY);
        Thread producer2 = new producer("P-2", queue,CAPACITY);
        Thread consumer1 = new consumer("C1", queue);
        Thread consumer2 = new consumer("C2", queue);
        Thread consumer3 = new consumer("C3", queue);
        producer1.start();
        producer2.start();
        consumer1.start();
        consumer2.start();
        consumer3.start();
    }
    public static class producer extends Thread
    {
        private final Queue<Integer> queue;
        private String name;
        private int maxSize;
        private int i=0;
        public producer(String name,Queue<Integer> queue,int maxSize)
        {
            super(name);
            this.queue=queue;
            this.name=name;
            this.maxSize=maxSize;
        }
        public void run()
        {
            while(true)
            {
                synchronized (queue)
                {
                    while(queue.size()==maxSize)
                    {
                        try {
                            System.out .println("Queue is full, Producer[" + name + "] thread waiting for " + "consumer to take something from queue.");
                            queue.wait();
                        }catch (Exception e)
                        {
                            e.printStackTrace();
                        }
                    }
                    System.out.println("[" + name + "] Producing value : +" + i);
                    queue.offer(i++);
                    queue.notifyAll();
                    try {
                        Thread.sleep(new Random().nextInt(1000));
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }

    }
    public static class consumer extends Thread
    {
        private final Queue<Integer> queue;
        private String name;
        public consumer(String name,Queue<Integer> queue)
        {
            super(name);
            this.queue=queue;
            this.name=name;
        }
        public void run()
        {
            while(true)
            {
                synchronized (queue)
                {
                    while(queue.size()==0)
                    {
                        try {
                            System.out.println("Queue is empty, Consumer[" + name + "] thread is waiting for Producer");
                            queue.wait();
                        }catch (Exception e)
                        {
                            e.printStackTrace();
                        }
                    }
                    int x = queue.poll();
                    System.out.println("[" + name + "] Consuming value : " + x);
                    queue.notifyAll();
                    try {
                        Thread.sleep(new Random().nextInt(1000));
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }
}

 第三個,基於Lock和condition的

import java.util.LinkedList;
import java.util.Queue;
import java.util.Random;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class producerByLock {
    private static final int CAPACITY = 5;
    private static final Lock lock = new ReentrantLock();
    private static final Condition fullCondition = lock.newCondition();     //隊列滿的條件
    private static final Condition emptyCondition = lock.newCondition();        //隊列空的條件
    public static void main(String[] args)
    {
        Queue<Integer> queue = new LinkedList<Integer>();
        Thread producer1 = new producer("P-1", queue,CAPACITY);
        Thread producer2 = new producer("P-2", queue,CAPACITY);
        Thread consumer1 = new consumer("C1", queue);
        Thread consumer2 = new consumer("C2", queue);
        Thread consumer3 = new consumer("C3", queue);
        producer1.start();
        producer2.start();
        consumer1.start();
        consumer2.start();
        consumer3.start();
    }
    public static class producer extends Thread
    {
        private final Queue<Integer> queue;
        private String name;
        private int maxSize;
        private int i=0;
        public producer(String name,Queue<Integer> queue,int maxSize)
        {
            super(name);
            this.queue=queue;
            this.name=name;
            this.maxSize=maxSize;
        }
        public void run()
        {
            while(true)
            {
                lock.lock();
                while(queue.size() == maxSize){
                    try {
                        System.out .println("Queue is full, Producer[" + name + "] thread waiting for " + "consumer to take something from queue.");
                        //條件不滿足,生產阻塞
                        fullCondition.await();
                    } catch (InterruptedException ex) {
                        ex.printStackTrace();
                    }
                }
                System.out.println("[" + name + "] Producing value : +" + i);
                queue.offer(i++);

                //喚醒其他所有生產者、消費者
                fullCondition.signalAll();
                emptyCondition.signalAll();

                //釋放鎖
                lock.unlock();

                try {
                    Thread.sleep(new Random().nextInt(1000));
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }

    }
    public static class consumer extends Thread
    {
        private final Queue<Integer> queue;
        private String name;
        public consumer(String name,Queue<Integer> queue)
        {
            super(name);
            this.queue=queue;
            this.name=name;
        }
        public void run()
        {
            while(true)
            {
                lock.lock();

                while(queue.isEmpty()){
                    try {
                        System.out.println("Queue is empty, Consumer[" + name + "] thread is waiting for Producer");
                        //條件不滿足,消費阻塞
                        emptyCondition.await();
                    } catch (Exception ex) {
                        ex.printStackTrace();
                    }
                }
                int x = queue.poll();
                System.out.println("[" + name + "] Consuming value : " + x);

                //喚醒其他所有生產者、消費者
                fullCondition.signalAll();
                emptyCondition.signalAll();

                //釋放鎖
                lock.unlock();

                try {
                    Thread.sleep(new Random().nextInt(1000));
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

2.Java多線程notify/notifyAll喚醒的是誰?

參考:https://blog.csdn.net/q5706503/article/details/84591159

3.什麼是時間片輪轉?

時間片輪轉說的是操作系統的一種調度算法,用於交互式系統,每一個進程都給分配一個時間片,然後進行快速的切換,但是速度很快,人看不到這些切換。另外還有優先級調度算法,多級反饋隊列算法(既有優先級又有時間片)

4.什麼是分佈式事務?

參考:https://blog.csdn.net/bjweimengshu/article/details/79607522

分佈式事務用於在分佈式系統中保證不同節點之間的數據一致性。

XA兩階段提交:

(1)在XA分佈式事務的第一階段,作爲事務協調者的節點會首先向所有的參與者節點發送Prepare請求。在接到Prepare請求之後,每一個參與者節點會各自執行與事務有關的數據更新,寫入Undo Log和Redo Log。如果參與者執行成功,暫時不提交事務,而是向事務協調節點返回“完成”消息。當事務協調者接到了所有參與者的返回消息,整個分佈式事務將會進入第二階段。

(2)作爲事務協調者的節點給所有事務參與者發出Commit請求。接到Commit請求之後,事務參與者節點會各自進行本地的事務提交,並釋放鎖資源。當本地事務完成提交後,將會向事務協調者返回“完成”消息。當事務協調者接收到所有事務參與者的“完成”反饋,整個分佈式事務完成。

在XA的第一階段,如果某個事務參與者反饋失敗消息,說明該節點的本地事務執行不成功,必須回滾。

於是在第二階段,事務協調節點向所有的事務參與者發送Abort請求。接收到Abort請求之後,各個事務參與者節點需要在本地進行事務的回滾操作,回滾操作依照Undo Log來進行。

5.常見的負載均衡算法?

(1)輪詢
將所有請求,依次分發到每臺服務器上,適合服務器硬件相同的場景。
優點:服務器請求數目相同;

缺點:服務器壓力不一樣,不適合服務器配置不同的情況;

(2)隨機
請求隨機分配到各臺服務器上。
優點:使用簡單;

缺點:不適合機器配置不同的場景

(3)最少鏈接
將請求分配到連接數最少的服務器上(目前處理請求最少的服務器)。
優點:根據服務器當前的請求處理情況,動態分配;

缺點:算法實現相對複雜,需要監控服務器請求連接數;

(4)Hash(源地址散列)
根據IP地址進行Hash計算,得到IP地址。
優點:將來自同一IP地址的請求,同一會話期內,轉發到相同的服務器;實現會話粘滯。

缺點:目標服務器宕機後,會話會丟失;

(5)加權
在輪詢,隨機,最少鏈接,Hash等算法的基礎上,通過加權的方式,進行負載服務器分配。

優點:根據權重,調節轉發服務器的請求數目;

缺點:使用相對複雜;

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章