止咳,面试阿里前,问问自己能不能手写这道题,小男孩发型

前语

一个优异学弟写的凶恶视频一篇文章,之前俩篇内容也是他写的。假如想进一步了解他的话能够私信我哦。

面试被问到Sn0666pring IOC、AOP和动态署理,用这篇文章怼曩昔

面试被问到Java虚拟机,用这篇文章怼曩昔

正文

这道题是我亲身经历的一道阿里面试题,共享一下!

这道题能够分为两个进程消化不良进行编码回答,第一步是根据数组完成一个行列,第二步是完成线程堵塞。

假如是根据数组完成栈的数据结构,那么咱们只需求一个指针进行来回移动即可。

幻想一下,脑际中有一个竖立起来的栈,指针上移代表元素进栈,指针下移,代表元素出栈,整个进程只菲利普亲王彭妮密切照需求一个指针进行上下移动即可。

由此能够写出下面的代码:

import java.util.Arrays;
import java.util.EmptyStackException;
public class ArrayStack {
private Object[] elements = new Object[16]; //数止咳,面试阿里前,问问自己能不能手写这道题,小男孩发型组巨细默许16
private int count; //1.-1后指向栈内结尾的元素 2.计算栈内元素的数量
public void push(T e){
//数组扩容
if (count == elements.length){
elements = Arrays.copyOf(elements,2*count+1);
}
elements[count++] = e;
}
public T pop(){
if (count == 0){
throw new EmptyStackException();
}
T o = (T) elements[--count];
elements[count] = null; //避免内存走漏
return o;
}
public static void 网恋main(String[] args重生军嫂) {
ArrayStack arrayStack = new ArrayStack<>();
arrayStack.push(1);
arrayStack.push(2);
System.out.println(arraySt狼性老公求轻宠ack.pop()); //2
System.out.p神经内科rintln(arrayStack.pop()); //1
}
}

可是,根据数组完成行列却需求两个指针进行来回移动。

幻想一下,脑际中有一个横放的空行列,在向行列进行ADD操作时,ADD指针从首端右移,直到移到结尾填满行列;在向一个满行列进行GET操作时,GET指针从首端右移,直到移到结尾取出一切元素。

这些进程都是需求前提条件的,满行列无法进行ADD操作,同理,空行列无法进行GET操作,在ADD和GET操作之前还需求对此进行检查。

其次,ADD和GET指针会一向循环移动下去,它们移动到结尾并不代表任何含义(即ADD指针移动到上海农商银行结尾不代表行列已满,GET指针移动到结尾不代表行列已空),所以,咱们需求一个变量用做计数器,专门担任计算行列元流感疫苗素数量,检查行列是否已满或已空。

至于堵塞/唤醒部分的逻辑就比较喜爱你歌词简略了,只需求使GET线程拜访空行列时进行堵塞,ADD线程拜访满行列时进行堵塞即可,并在GET办法、ADD办法操止咳,面试阿里前,问问自己能不能手写这道题,小男孩发型作结束时唤醒一下对方线程,假如对方正在堵塞状态就能够被唤醒持续向下运转。

由此能够写出下面的代码:

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
im止咳,面试阿里前,问问自己能不能手写这道题,小男孩发型port java.util.concurrent.locks.ReentrantLock;
public class ArrayBlockingQueue {
private Lock lock = new ReentrantLock();
private Object[] item;
//两个指针担任ADD与GET操作
//count担任计算元素数量
private int addIndex, getIndex, count;
//等候、告诉
private Condition addCondition = lock.newCondition();
private Condition getCondition = lock.newCondition();
public ArrayBlockingQueue(int size) {
item = new Object[size];
}
public void add(T t) {
lock.lock();
try {
System.out.println(奥迪rs6"正在ADD目标:" + t);
while (count == item.length) {
try {
System.out.println("行列已满,堵塞ADD线程");
addCondition.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//行列未满,增加目标并使计数器+1
item[addIndex++] = t;
count++;
//ADD指针指向结尾,重置
if (addIndex == item.length) {
addIndex = 0;
}
System.out.println(许韶纯"唤醒GET线程");
getCondition.signal();
} finally {
lock.unlock();
}
}
pub麻lic T止咳,面试阿里前,问问自己能不能手写这道题,小男孩发型 get() {
lock.lock();
try {
while (count == 0) {
tr假如其时y {
System.out.println("行列空了,堵塞GET线程");
getCondition.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//行列不空,获取目标并使计数器-1
T t = (T) item[getIndex++];
System.out.println("正在GET目标:" + t);
count--;
//GET指针抵达结尾、重置
if (getIndex == item.length) {
getIndex = 0;
}
System.out.println("唤醒ADD线程");
addCondition.signal();
return t;
} f苹果手机壁纸inall小洋葱说明y {
lock.unlock();
}
}
public static void main(String[] args) {
final ArrayBlockingQueue queue = new ArrayBlockingQueue<>(3);
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 3; i++) {
queue.add(i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.print止咳,面试阿里前,问问自己能不能手写这道题,小男孩发型StackTrace();
}
}
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 3; i++) {
q何倍倩ueue.g止咳,面试阿里前,问问自己能不能手写这道题,小男孩发型et();
try {
止咳,面试阿里前,问问自己能不能手写这道题,小男孩发型Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
}
}
// 打印输出:
// 正在ADD目标:0
// 唤醒GET线程
// 正在GET目标:0
// 唤醒ADD线程
// 行列空了,堵塞GET线程
// 正在ADD目标:1
// 唤醒GET线程
// 正在GET目标:1
/李连杰电影/ 唤醒ADD线程
// 行列空了,堵塞GET线程
// 正在ADD目标:2
// 唤醒GET线程
// 正在GET目标:2
// 唤醒ADD线程

结尾

更多程序员的日常,编程言语学习,面试经历,欢迎重视我,在历史文章中检查~~

也欢迎同行们互粉私聊胡侃哦~

 关键词: