多态实现
父类的引用指向子类对象
生产者消费者手写
import java.util.*;
class Storage {
	private final int MAX_SIZE=100;
	private LinkedList list = new LinkedList();

	public void produce(int num) {
		synchronized(list) {
			while(list.size()+num>MAX_SIZE) {
				System.out.println("暂时不能执行生产任务");
				try {
					list.wait();
				} catch(InterruptedException e) {
					e.printStackTrace();
				}
			}
			for (int i=0; i<num; i++) {
				list.add(new Object());
			}
			System.out.println("仓库中有产品"+list.size());
			list.notifyAll();
		}
	}

	public void consume(int num) {
		synchronized(list) {
			while(list.size()<num) {
				System.out.println("暂时不能执行消费任务");
				try {
					list.wait();
				} catch(InterruptedException e) {
					e.printStackTrace();
				}
			}
			for (int i=0; i<num; i++) {
				list.remove();
			}
			System.out.println("仓库中有产品"+list.size());
			list.notifyAll();
		}
	}
}
class Producer extends Thread {
	private int num;
	public Storage storage;
	public Producer(Storage storage) {
		this.storage=storage;
	}
	public void setNum(int num) {
		this.num=num;
	}
	public void run() {
		storage.produce(num);
	}
}
class Consumer extends Thread {
	private int num;
	public Storage storage;
	public Consumer(Storage storage) {
		this.storage=storage;
	}
	public void setNum(int num) {
		this.num=num;
	}
	public void run() {
		storage.consume(num);
	}
}
public class Test {
	public static void main(String[] args) {
		Storage storage = new Storage();
		Producer p1 = new Producer(storage); 
		Producer p2 = new Producer(storage); 
		Producer p3 = new Producer(storage); 
		Producer p4 = new Producer(storage); 
		Producer p5 = new Producer(storage); 

		Consumer c1 = new Consumer(storage);
		Consumer c2 = new Consumer(storage);
		Consumer c3 = new Consumer(storage);
		p1.setNum(10);
		p2.setNum(20);
		p3.setNum(30);
		p4.setNum(40);
		p5.setNum(50);

		c1.setNum(60);
		c2.setNum(20);
		c3.setNum(100);

		c1.start();
		c2.start();
		c3.start();
		p1.start();
		p2.start();
		p3.start();
		p4.start();
		p5.start();
	}
}
SQL查询语句手写
SELECT 列名称 FROM 表名称
Mybatis批量查询手写

HashMap,HashTable,ConcurrentHashmap区别,底层源码
(参考博客:https://www.cnblogs.com/heyonggang/p/9112731.html
HashTable:
底层数组+链表实现,无论key还是value都不能为null,线程安全,
实现线程安全的方式是在修改数据时锁住整个HashTable,效率低,
ConcurrentHashMap做了相关优化。
HashMap:
底层数组+链表实现,可以存储null键和null值,线程不安全。
ConcurrentHashMap:
底层采用分段的数组+链表实现,线程安全。
通过把整个Map分成N个Segment,可以提供相同的线程安全,但是效率提升N倍。
为什么要使用ConcurrentHashMap
在并发编程中使用HashMap可能导致程序死循环,而线程安全的HashTable效率又非常低下,
基于以上两个原因,便有了ConcurrentHashMap的登场机会。
HashMap在并发执行put操作时会引起死循环,是因为多线程会导致HashMap的Entry链表
形成环形数据结构,一旦形成环形数据结构,Entry的next节点永远不为空,就会产生死循环
获取Entry。
HashTable容器在并发环境下效率低下的原因是所有访问HashTable的线程都必须竞争同一把锁。
ConcurrentHashMap使用锁分段技术,将数据分成一段一段地存储,然后给每一段数据配一把锁,
当一个线程占用锁访问其中一个段数据的时候,其他段的数据也能被其他线程访问。

内存泄漏的情况有哪些
内存泄漏的定义:一个不再被程序使用的对象或变量还在内存中占有存储空间。
1、静态集合类,如HashTable、LinkedList等,如果这些容器为静态的,那么他们的
生命周期与程序一致,则容器中的对象在程序结束之前不能被释放,从而造成内存泄漏。
2、数据库连接,网络连接,IO连接等,当不再使用连接时需要调用close方法来释放连接。
只有连接关闭时,垃圾回收器才会回收对应的对象。否则,如果在访问数据库的过程中,
对Connection、Statement或ResultSet不显性地关闭,将会造成大量的对象无法被回收,从而
引起内存泄漏。
3、变量不合理的作用域。一般而言,如果一个变量的定义的作用范围大于其使用范围,很可能造成
内存泄漏。
4、内部类持有外部类
如果一个外部类的实例对象的方法返回了一个内部类的实例对象,这个内部类对象被长期引用了,
即使那个外部类实例对象不再被使用,但由于内部类持有外部类的实例对象,这个外部类对象将不会被垃圾回收,这也会造成内存泄露。
5、改变哈希值,
当一个对象被存储进HashSet集合中以后,就不能修改这个对象中的那些参与计算哈希值的字段了,
否则,对象修改后的哈希值与最初存储进HashSet集合中时的哈希值就不同了,在这种情况下,
即使在contains方法使用该对象的当前引用作为的参数去HashSet集合中检索对象,也将返回找不到对象的结果,
这也会导致无法从HashSet集合中单独删除当前对象,造成内存泄露

classpath,path的区别
path是windows查找.exe文件的路径;classpath是jvm查找.class文件的路径

JVM运行过程

GC机制讲一讲 可能还有,记不清了

线程池,阻塞队列

http ,https区别

非对称加密和对称加密
对称加密:加密密钥和解密密钥使用相同的密码体制。
非对称加密:使用不同的加密密钥和解密密钥。
数据加密标准DES属于对称密钥密码体制。
DES的保密性仅取决于对密钥的保密,而算法是公开的。
公钥加密,私钥解密

如何设计一个服务器(socket相关)

IDEA常用快捷键:
1、智能提示:Ctrl+Space
Alt+Enter:快速修复错误
2、代码生成
Alt+Insert
3、Ctrl+/:注释

如何使得浏览器加载请求可以稳定打到后台而不使用浏览器缓存(请求中加一个随机值参数)

spring事务写在哪一部分,为什么不写在DAO,Controller层

数据库驱动为什么使用反射调用不直接new
为什么一定要使用反射呢?因为反射是运行时根据全限定类名动态生成的Class对象,
可以把这个全类名写在xml或者properties中去,
不仅从代码上解耦和,而且需要更换数据库时,不需要进行代码的重新编译。