问题
- 编写一个单例模式?
- 对一组数进行升序排序,使用快排实现?
- 使用多线程实现生产者消费者模型?
- Java 中==和 equals()的区别.?
- JDBC 操作数据库的步骤有哪些?
- 重载和重写的区别.?
- 什么是序列化与反序列化.?
- 线程的状态有哪些.?
- 线程池执行流程是什么.?
- 什么是死锁?造成线程死锁的四个条件是什么.
答案
1. 编写一个单例模式?
//都是线程安全的
//静态内部类
public class staticInnerClass(){
private static volatile staticInnerClass doubleCheck;
private staticInnerClass(){}
//静态内部类 创建 静态内部类装载是线程安全的
public static class staticInnerClassInstance{
//创建类对象
private static final staticInnerClass innerClass=new staticInnerClass();
}
//暴露get方法
public static staticInnerClass getInstance(){
return staticInnerClassInstance.innerClass;
}
}
//双重检测
public class DoubleCheck{
private static volatile DoubleCheck doubleCheck;
private DoubleCheck(){}
public static synchronized DoubleCheck getInstance(){
if(doubleCheck==null){
synchronized(DoubleCheck.class){
if(doubleCheck==null){
doubleCheck=new DoubleCheck();
}
}
}
return doubleCheck;
}
}
2. 对一组数进行升序排序,使用快排实现?
public static void quicklySort(int[] nums,int low,int high){
int i,j,temp;
if(low>high){
return;
}
i=low;
j=high;
temp=nums[i];
//取最左边的数作为基准数,先从右侧比较,再比较左侧
while(i<j){
while(temp<=nums[j]&&i<j){
//右边的数大于基准数,则右边指针前移
j--;
}
if(i<j){
//小于的话,把右边的数放在左边指针的位置,左边指针右移
nums[i++]=nums[j];
}
while(temp>=nums[i]&&i<j){
//左边的数字小于基准数,指针向后移动
i++;
}
if(i<j){
//大于的话,左边的数放在右边指针的位置,右边指针前移
num[j--]=num[i];
}
}
nums[i]=temp;
quicklySort(nums,low,j-1);
quicklySort(nums,j+1,high);
}
3. 使用多线程实现生产者消费者模型?
//面包容器
public class BreadContainer(){
private Bread[] breads;
private int size;
public BreadContainer(int initSize){
breads=new Breads[initSize];
}
//生产者
public synchronized void add(Bread bread){
while(size==breads.length){
System.out.print(Thread.currentThread.getName+":面包柜满了,赶紧销售");
wait();
}
breads[size]=bread;
size++;
System.out.print(Thread.currentThread.getName+":生产第"+size+"个面包");
notifyAll();
}
//消费者
public synchronized void remove(){
while(size==0){
System.out.print(Thread.currentThread.getName+":面包买完了,赶紧生产");
wait();
}
System.out.print(Thread.currentThread.getName+":卖出第"+size+"个面包");
size--;
notifyAll();
}
}
//测试类
BreadContainer container=new BreadContainer();
new Thread(new Runnable(){
//重写
public void run(){
Bread bread=new Bread();
container.add(bread);
}
},"生产者").start;
new Thread(new Runnable(){
//重写
public void run(){
container.remove();
}
},"消费者").start;
4.Java 中==和 equals()的区别.?
- 基本类型:==比较的是值是否相同,不能使用equals进行判断
- 引用类型中:==判断两个对象的内存地址是否相同;如果没有重写equals方法,则使用Object类中的equals方法,判断两个对象是否为同一对象(Object类中的equals使用双等进行判断),如果重写了则按照重写过后的规则比较两个对象是否相等。
5. JDBC 操作数据库的步骤有哪些?
连接数据库(加载驱动、注册驱动、创建Connection对象)
编写SQL语句
创建预处理对象(PrepareStatement对象)
为SQL语句中的?占位符赋值
执行SQL语句,并返回结果
处理结果(ResultSet对象)
释放资源
6. 重载和重写的区别.?
- 重载(方法名复用)发生在同一类中,多个方法之间,方法的参数列表不同(个数不同、顺序不同、类型不同),与访问权限修饰符和返回结果无关。重载发生在编译期,构造器可以重载
- 重写(实现多态)发生在子类之间,除了访问权限和异常抛出外,方法的声明和父类的某个方法的声明必须一致,访问权限大于等于父类,抛出的异常小于等于父类。
- 父类中被private、final、static修饰的方法不能被重写。重写发生在运行期,构造方法不能被重写。
7. 什么是序列化与反序列化.?
- 序列化是将对象转换为字节流的过程
- 反序列化是将字节流转换为对象的过程
- 被序列化的对象需要实现Serializable序列化接口,该接口是标志性接口
- 为保证序列化和反序列化的稳定进行,建议在类上添加序列化版本号
- 可以使用transient关键字,指定成员变量不被序列化
8. 线程的状态有哪些.?
- 新建状态New:线程被创建,但是没有调用start()方法
- 可运行状态Runnable:调用start方法后线程进入可运行状态
- 运行状态Running:可运行状态的线程在获得CPU资源后,进入可运行状态
- 阻塞状态Blocked:调用wait()、sleep()、在获取同步锁时,若该同步锁被别的线程占有等情况
- 消亡状态
9. 线程池执行流程是什么.?
- 提交一个线程任务,当线程池中存活的核心线程小于线程数时,就创建一个核心线程去执行任务
- 如果线程池核心线程数已满,提交的任务就放到任务队列进行等待执行
- 当线程池中存活的线程数已经达到核心线程最大数,任务队列也已满,此时判断线程数是否达到最大数量,如果没有达到,则会创建一个非核心线程执行提交的任务
- 如果当前的线程达到了最大线程数,还有新的任务提交则会采用拒绝策略处理。
10. 什么是死锁?造成线程死锁的四个条件是什么.
多个线程同时被阻塞,他们中的一个或多个都在等待某个资源的被释放,由于线程被无限期阻塞,因此程序不可能正常终止。条件:①互斥条件 ②请求与保持条件 ③不剥夺条件 ④循环等待条件