面试常用设计Demo
生产者消费者
package sort;
import java.util.ArrayList;
public class ProducerConsumerTest {
public static void main(String[] args) {
ProductPool productPool = new ProductPool();
//线程一生成10个产品
new Thread(new Producer(productPool, 1, 10)).start();
//线程二消费10个产品
new Thread(new Consumer(productPool, 1, 10)).start();
}
}
//产品池
class ProductPool{
private static final int maxSize = 5;
private static final ArrayList<Integer> pool = new ArrayList<>();
public void get(){
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (pool){
while (pool.size() == 0){ //池为空阻塞,让出锁资源,while防止虚假唤醒
try {
System.out.println("pool is empty, please wait...");
pool.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
int tmp = pool.remove(0);//消费
System.out.println("consume: " + tmp);
pool.notifyAll();
}
}
public void set(int product){
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (pool){
while (pool.size() == maxSize){
try {
System.out.println("pool is full, please wait...");
pool.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
pool.add(product);
System.out.println(" product: " + product);
pool.notifyAll();
}
}
}
//生产者
class Producer extends Thread{
int id;
int size;
ProductPool pools;
Producer(ProductPool pool, int id, int size){
this.pools = pool;
this.id = id;
this.size = size;
}
@Override
public void run() {
for(int i = 0; i < size; ++i){
pools.set(i);
}
}
}
//消费者
class Consumer extends Thread{
int id;
int size;
ProductPool pools;
Consumer(ProductPool pool, int id, int size){
this.pools = pool;
this.id = id;
this.size = size;
}
@Override
public void run() {
for(int i = 0; i < size; ++i){
pools.get();
}
}
}
单例类
枚举类方式
public class SingletonClass {
public SingletonClass(){}
public SingletonClass getSingletonClass(){
return Singleton.INSTANCE.singletonClass;
}
private enum Singleton{
INSTANCE;
SingletonClass singletonClass;
Singleton(){
singletonClass = new SingletonClass();
}
SingletonClass getInstance(){
return singletonClass;
}
}
}
双重检测锁方式
public class SingletonClass {
private volatile static SingletonClass singletonClass;
public SingletonClass(){}
public SingletonClass getSingletonClass(){
if(singletonClass == null){
synchronized (SingletonClass.class){
if(singletonClass == null){
singletonClass = new SingletonClass();
}
}
}
return singletonClass;
}
}
CAS实现
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
public class CasDemo2 {
public static void main(String[] args) throws InterruptedException {
long start = System.currentTimeMillis();
/*使用栅栏保证让100个线程全部执行完后再执行后面的代码*/
CountDownLatch countDownLatch = new CountDownLatch(100);
Resource1 resource = new Resource1();
//模拟100线程进行CAS加操作,每个线程将num加10
for (int i = 0; i < 100; i++) {
new Thread(()->{
try {
resource.add();
} catch (InterruptedException e) {
e.printStackTrace();
}
countDownLatch.countDown();
}).start();
}
countDownLatch.await();
System.out.println("num="+resource.getNum());
long end = System.currentTimeMillis();
System.out.println("耗时"+(end - start));//164
}
}
class Resource1{
private static int num=0;
public int getNum(){
return num;
}
public void add() throws InterruptedException {
for (int i = 0; i < 10; i++) {
//模拟延迟
TimeUnit.MICROSECONDS.sleep(5);
while(!ComAndSwap(num,num+1));
}
}
//expectNum,预期值 NewNum,新值
public synchronized boolean ComAndSwap(int expectNum,int NewNum){
if(expectNum==num){
num=NewNum;
return true;
}
return false;
}
}
LRU缓存
利用LinkedHashMap
class LRUCache {
private LinkedHashMap<Integer,Integer> map;
int capacity;
public LRUCache(int capacity) {
this.capacity = capacity;
this.map = new LinkedHashMap<>();
}
public int get(int key) {
//存在该元素就取出,然后再加入(重新放到链尾)
if(map.containsKey(key)){
int tmp = map.remove(key);
map.put(key, tmp);
return tmp;
}
return -1;
}
public void put(int key, int value) {
if(map.containsKey(key)){
map.remove(key);
}
//如果元素数量达到容量上限,把链头元素删除
if(map.size() == capacity){
map.remove(map.entrySet().iterator().next().getKey());
}
map.put(key, value);
}
}
自定义结构实现
class LRUCache {
private class Node{
int key;
int value;
Node pre;
Node next;
public Node(){}
public Node(int key, int value){
this.key = key;
this.value = value;
}
}
//基本结构:map加双端链表
private Map<Integer,Node> LRUMap = new HashMap<Integer, Node>();
private int capacity;
//首尾指针
private Node head, tail;
public LRUCache(int capacity){
this.capacity = capacity;
this.head = new Node();
this.tail = new Node();
head.next = tail;
tail.pre = head;
}
//获取元素,没有返回-1;有则返回值,并且把该节点移动到第一个
public int get(int key){
if(LRUMap.containsKey(key)){
Node node = LRUMap.get(key);
moveToHead(node);
return node.value;
}
return -1;
}
//put元素,存在则移动节点到首位置,并更新值;否则判断容量是否到达上限,到达移除最后一个元素(Node移除,map也要移除),再加入新节点,放入首位置
public void put(int key, int value){
if(LRUMap.containsKey(key)){
Node node = LRUMap.get(key);
moveToHead(node);
node.value = value;
return;
}
Node node = new Node(key, value);
if(LRUMap.size() == capacity){
Node delNode = removeLast();
LRUMap.remove(delNode.key);
}
LRUMap.put(key, node);
addToHead(node);
}
//删除对应节点
public void removeNode(Node node){
node.pre.next = node.next;
node.next.pre = node.pre;
}
//把节点添加到首部
public void addToHead(Node node){
node.next = head.next;
node.next.pre = node;
head.next = node;
node.pre = head;
}
//移动节点到首位置:先删除原位置的节点,再增加到首部
public void moveToHead(Node node){
removeNode(node);
addToHead(node);
}
//删除最后一个元素
public Node removeLast(){
Node node = tail.pre;
removeNode(node);
return node;
}
}
栈实现队列
class MyQueue {
Stack<Integer> stack1, stack2;
int front;
/** Initialize your data structure here. */
public MyQueue() {
stack1 = new Stack<>();
stack2 = new Stack<>();
}
/** Push element x to the back of queue. */
public void push(int x) {
if(stack1.isEmpty()){
front = x;
}
stack1.push(x);
}
/** Removes the element from in front of queue and returns that element. */
public int pop() {
if(stack2.isEmpty()){
if(stack1.isEmpty()){
return -1;
}else{
while(!stack1.isEmpty()){
stack2.add(stack1.pop());
}
}
}
return stack2.pop();
}
/** Get the front element. */
public int peek() {
if(!stack2.isEmpty()){
return stack2.peek();
}
return front;
}
/** Returns whether the queue is empty. */
public boolean empty() {
return stack1.isEmpty() && stack2.isEmpty();
}
}
队列实现栈
class MyStack {
Queue<Integer> queue1;
Queue<Integer> queue2;
/** Initialize your data structure here. */
public MyStack() {
queue1 = new LinkedList<Integer>();
queue2 = new LinkedList<Integer>();
}
/** Push element x onto stack. */
public void push(int x) {
queue2.offer(x);
while (!queue1.isEmpty()) {
queue2.offer(queue1.poll());
}
Queue<Integer> temp = queue1;
queue1 = queue2;
queue2 = temp;
}
/** Removes the element on top of the stack and returns that element. */
public int pop() {
return queue1.poll();
}
/** Get the top element. */
public int top() {
return queue1.peek();
}
/** Returns whether the stack is empty. */
public boolean empty() {
return queue1.isEmpty();
}
}