https://www.jianshu.com/p/4fe55c1334e3
question:
1.内部类和静态内部类的区别
2.如何使一个类不能被继承
3.写一个单例模式,保证线程安全的
4.如果你写的这个单例被继承,然后多次实例化,还是单例吗(提示构造方法是private的类不能被继承)
5.代码:带括号的表达式求值,如:1加(3减2)
6.网络五层架构,http在哪一层
7.tcp和udp的区别
8.tcp三次握手过程,为什么要有第三次
9.数据库事务四个性质,一致性是什么
10.死锁是什么,怎么产生,如何避免
11.数组和链表的区别
12.二叉排序树是什么,查找的时间复杂度,怎么降低时间复杂度
answer:
1.内部类和静态内部类的区别
public class InnerClassTest {
private int aNum = 1;
public static void main(String[] args) {
new InnerClassTest().a();
}
private InnerClass innerclassObj = new InnerClass();
private void a() {
new InnerClass().innerMethod();
new StaticInnerClass().innerMethod();
}
void b() {
}
private void c() {
}
public void d(){
}
private class InnerClass {
private void innerMethod() {
c();
aNum = 2;
}
}
static class StaticInnerClass {
private void innerMethod() {
d();
}
}
}
- 静态内部类是指被声明为static的内部类,可不依赖外部类实例化;而非静态内部类需要通过生成外部类来间接生成。
- 静态内部类只能访问外部类的静态成员变量和静态方法,而非静态内部类由于持有对外部类的引用,可以访问外部类的所用成员
- 普通内部类
-
public class MyService extends Service { public MyService() { } private DownloadBinder mBinder = new DownloadBinder(); class DownloadBinder extends Binder { public void startDownload() { Log.d("MyService", "startDownload executed"); } public int getProgress() { Log.d("MyService", "getProgress executed"); return 0; } } @Override public IBinder onBind(Intent intent) { return mBinder; } @Override public void onCreate() { super.onCreate(); Log.d("MyService", "onCreate executed"); } @Override public int onStartCommand(Intent intent, int flags, int startId) { Log.d("MyService", "onStartCommand executed"); return super.onStartCommand(intent, flags, startId); } @Override public void onDestroy() { super.onDestroy(); Log.d("MyService", "onDestroy executed"); } }
- 静态内部类
-
package com.example.demo; public class Outer { private int varFromOuter; private Inner innerObj; public static class Inner{ private String varFromInner; private int size; public String getVarFromInner() { return varFromInner; } public void setVarFromInner(String varFromInner) { this.varFromInner = varFromInner; } public int getSize() { return size; } public void setSize(int size) { this.size = size; } } public int getVarFromOuter() { return varFromOuter; } public void setVarFromOuter(int varFromOuter) { this.varFromOuter = varFromOuter; } public Inner getInnerObj() { return innerObj; } public void setInnerObj(Inner innerObj) { this.innerObj = innerObj; } } 外部引用 Outer outer = new Outer(); Outer.Inner inner = new Outer.Inner(); inner.setVarFromInner("abc"); inner.setSize(0); outer.setInnerObj(inner);
2.如何使一个类不能被继承
- 使用final关键字;放在类前面比如looper
public final class Looper { 。。。}
- 使用私有构造器;
1 public final class InitTest{ 2 private InitTest(){} 3 } 比如单例模式 构造函数是私有的
3.写一个单例模式,保证线程安全的
synchronized 方法(总结:就是这块代码只能有一个线程的得到执行,在锁没有释放的时候。但是这块代码可能会被cpu调度,时间片切换其他线程先执行,即这个代码执行如果有多个流程 可能会被分散到几个时间片里执行,并不是在一个时间片内)
volatile 作用是防止指令重排序。
每个类实例对应一把锁,每个 synchronized 方法都必须获得调用该方法的类实例的锁方能执行,否则所属线程阻塞,方法一旦执行,就独占该锁,直到从该方法返回时才将锁释放,此后被阻塞的线程方能获得该锁,重新进入可执行状态。这种机制确保了同一时刻对于每一个类实例,其所有声明为 synchronized 的成员函数中至多只有一个处于可执行状态(因为至多只有一个能够获得该类实例对应的锁),从而有效避免了类成员变量的访问冲突(只要所有可能访问类成员变量的方法均被声明为 synchronized)。
两种 一种同步方法 损失效率。每次获取锁时
public class Singleton {
private static Singleton uniqueSingleton;
private Singleton() {
}
public synchronized Singleton getInstance() {
if (null == uniqueSingleton) {
uniqueSingleton = new Singleton();
}
return uniqueSingleton;
}
}
第二种 双重检查锁
public class Singleton {
private volatile static Singleton uniqueSingleton;
private Singleton() {
}
public Singleton getInstance() {
if (null == uniqueSingleton) {
synchronized (Singleton.class) {
if (null == uniqueSingleton) {
uniqueSingleton = new Singleton();
}
}
}
return uniqueSingleton;
}
}
4.如果你写的这个单例被继承,然后多次实例化,还是单例吗
和第二个问题 关联
10.死锁是什么,怎么产生,如何避免
两个线程想要执行都要获取对方持有的锁
从这个例子也可以反映出,死锁是因为多线程访问共享资源,由于访问的顺序不当所造成的,通常是一个线程锁定了一个资源A,而又想去锁定资源B;在另一个线程中,锁定了资源B,而又想去锁定资源A以完成自身的操作,两个线程都想得到对方的资源,而不愿释放自己的资源,造成两个线程都在等待,而无法执行的情况。
https://www.cnblogs.com/xiaoxi/p/8311034.html
package com.demo.test;
/**
* 一个简单的死锁类
* t1先运行,这个时候flag==true,先锁定obj1,然后睡眠1秒钟
* 而t1在睡眠的时候,另一个线程t2启动,flag==false,先锁定obj2,然后也睡眠1秒钟
* t1睡眠结束后需要锁定obj2才能继续执行,而此时obj2已被t2锁定
* t2睡眠结束后需要锁定obj1才能继续执行,而此时obj1已被t1锁定
* t1、t2相互等待,都需要得到对方锁定的资源才能继续执行,从而死锁。
*/
public class DeadLock implements Runnable{
private static Object obj1 = new Object();
private static Object obj2 = new Object();
private boolean flag;
public DeadLock(boolean flag){
this.flag = flag;
}
@Override
public void run(){
System.out.println(Thread.currentThread().getName() + "运行");
if(flag){
synchronized(obj1){
System.out.println(Thread.currentThread().getName() + "已经锁住obj1");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized(obj2){
// 执行不到这里
System.out.println("1秒钟后,"+Thread.currentThread().getName()
+ "锁住obj2");
}
}
}else{
synchronized(obj2){
System.out.println(Thread.currentThread().getName() + "已经锁住obj2");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized(obj1){
// 执行不到这里
System.out.println("1秒钟后,"+Thread.currentThread().getName()
+ "锁住obj1");
}
}
}
}
}
package com.demo.test;
public class DeadLockTest {
public static void main(String[] args) {
Thread t1 = new Thread(new DeadLock(true), "线程1");
Thread t2 = new Thread(new DeadLock(false), "线程2");
t1.start();
t2.start();
}
}
hashmap操作 通过迭代器获取key和value
private HashMap<String, tring, String> hashmap = new HashMap<>();
Iterator<String> iterator2 = hashmap.keySet().iterator();
while (iterator2.hasNext()) {
String key = iterator2.next();
List<String> value = hashmap.get(key);
if (value != null && value.contains(keyword)) {
ret = key;
}
}
Iterator<Map.Entry<String, String>> iterator = hashmap.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry<String, List<String>> entry = iterator.next();
String key = entry.getKey();
list.addAll(entry.getValue());
}