🐓 sleep和wait区别
1.sleep方法
属于Thread类中的方法
释放cpu给其它线程 不释放锁资源
sleep(1000) 等待超过1s被唤醒
2.wait方法
属于Object类中的方法
释放cpu给其它线程,同时释放锁资源
wait(1000) 等待超过1s被唤醒
wait() 一直等待需要通过notify或者notifyAll进行唤醒
wait 方法必须配合 synchronized 一起使用
#### 锁释放时机代码演示
public static void main(String[] args) {
Object o = new Object();
Thread thread = new Thread(() -> {
synchronized (o) {
System.out.println("新线程获取锁时间:" + LocalDateTime.now() + " 新线程名称:" + Thread.currentThread().getName());
try {
//wait 释放cpu同时释放锁
o.wait(2000);
//sleep 释放cpu不释放锁
//Thread.sleep(2000);
System.out.println("新线程获取释放锁锁时间:" + LocalDateTime.now() + " 新线程名称:" + Thread.currentThread().getName());
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
});
thread.start();
try {
Thread.sleep(100);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println("主线程获取锁时间:" + LocalDateTime.now() + " 主线程名称:" + Thread.currentThread().getName());
synchronized (o){
System.out.println("主线程获取释放锁锁时间:" + LocalDateTime.now() + " 主线程名称:" + Thread.currentThread().getName());
}
}
🐓 ==和equals区别
1.==
如果比较的是基本数据类型,那么比较的是变量的值
如果比较的是引用数据类型,那么比较的是地址值(两个对象是否指向同一块内存)
2.equals
如果没重写equals方法比较的是两个对象的地址值
如果重写了equals方法后我们往往比较的是对象中的属性的内容
equals方法是从Object类中继承的,默认的实现就是使用==
🐓 String buffer和String builde
1.StringBuffer 与 StringBuilder 中的方法和功能完全是等价的,
2.只是StringBuffer 中的方法大都采用了 synchronized 关键字进行修饰,因此是线程安全的,而 StringBuilder 没有这个修饰,可以被认为是线程不安全的。
3.在单线程程序下,StringBuilder效率更快,因为它不需要加锁,不具备多线程安全而StringBuffer则每次都需要判断锁,效率相对更低
🐓 ArrarList和LinkedList区别
1.ArrayList是实现了基于动态数组的数据结构,LinkedList基于链表的数据结构。
2.对于随机访问get和set,ArrayList效率优于LinkedList,因为LinkedList要移动指针。
3.对于新增和删除操作add和remove,LinkedList比较占优势,因为ArrayList要移动数据。 这一点要看实际情况的。若只对单条数据插入或删除,ArrayList的速度反而优于LinkedList。但若是批量随机的插入删除数据,LinkedList的速度大大优于ArrayList. 因为ArrayList每插入一条数据,要移动插入点及之后的所有数据。
🐓 HashMap底层
hashMap在1.8之前的底层结构是数组+链表,在1.8及以后使用的底层结构式数组+链表+红黑树
他们的区别还有put时的resize()方法的不同。
1.数组 Node<K,V>[] table ,哈希表,根据对象的key的hash值进行在数组里面是哪个节点
2.链表的作用是解决hash冲突,将hash值取模之后的对象存在一个链表放在hash值对应的槽位
3.红黑树 JDK8使用红黑树来替代超过8个节点的链表,主要是查询性能的提升,从原来的O(n)到O(logn)
4.通过hash碰撞,让HashMap不断产生碰撞,那么相同的key的位置的链表就会不断增长,当对这个Hashmap的相应位置进行查询的时候,就会循环遍历这个超级大的链表,性能就会下降,所以改用红黑树
🐓 HashMap和HashTable区别
1.线程安全性不同
HashMap是线程不安全的,HashTable是线程安全的,其中的方法是Synchronized,在多线程并发的情况下,可以直接使用HashTable,但是使用HashMap时必须自己增加同步处理
2.是否提供contains方法
HashMap只有containsValue和containsKey方法;HashTable有contains、containsKey和containsValue三个方法,其中contains和containsValue方法功能相同。
3.key和value是否允许null值
Hashtable中,key和value都不允许出现null值。HashMap中,null可以作为键,这样的键只有一个;可以有一个或多个键所对应的值为null。
4.数组初始化和扩容机制
HashTable在不指定容量的情况下的默认容量为11,而HashMap为16,Hashtable不要求底层数组的容量一定要为2的整数次幂,而HashMap则要求一定为2的整数次幂,Hashtable扩容时,将容量变为原来的2倍加1,而HashMap扩容时,将容量变为原来的2倍。
🐓 线程的创建方式
1.继承Thread类创建线程
2.实现Runnable接口创建线程
3.使用Callable和Future创建线程 有返回值
4.使用线程池创建线程
#### 代码演示
import java.util.concurrent.*;
public class threadTest{
public static void main(String[] args) throws ExecutionException, InterruptedException {
//继承thread
ThreadClass thread = new ThreadClass();
thread.start();
Thread.sleep(100);
System.out.println("#####################");
//实现runnable
RunnableClass runnable = new RunnableClass();
new Thread(runnable).start();
Thread.sleep(100);
System.out.println("#####################");
//实现callable
FutureTask futureTask = new FutureTask(new CallableClass());
futureTask.run();
System.out.println("callable返回值:" + futureTask.get());
Thread.sleep(100);
System.out.println("#####################");
//线程池
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(1, 1, 2, TimeUnit.SECONDS, new ArrayBlockingQueue<>(10));
threadPoolExecutor.execute(thread);
threadPoolExecutor.shutdown();
Thread.sleep(100);
System.out.println("#####################");
//使用并发包Executors
ExecutorService executorService = Executors.newFixedThreadPool(5);
executorService.execute(thread);
executorService.shutdown();
}
}
class ThreadClass extends Thread{
@Override
public void run() {
System.out.println("我是继承thread形式:" + Thread.currentThread().getName());
}
}
class RunnableClass implements Runnable{
@Override
public void run(){
System.out.println("我是实现runnable接口:" + Thread.currentThread().getName());
}
}
class CallableClass implements Callable<String> {
@Override
public String call(){
System.out.println("我是实现callable接口:");
return "我是返回值,可以通过get方法获取";
}
}