java面经查缺补漏之三十六天(前天面试完美团,不知道是否凉凉,今天主要学生产者消费者模型)
1.手写一个生产者消费者模型?
查了一下,这篇讲的是最好的!一共有三种方式,阻塞队列,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等算法的基础上,通过加权的方式,进行负载服务器分配。
优点:根据权重,调节转发服务器的请求数目;
缺点:使用相对复杂;