-
线程和进程的区别
根本区别:进程是操作系统资源分配的基本单位,而线程是任务调度和执行的基本单位
在开销方面:每个进程都有独立的代码和数据空间(程序上下文),程序之间的切换会有较大的开销;线程可以看做轻量级的进程,同一类线程共享代码和数据空间,每个线程都有自己独立的运行栈和程序计数器(PC),线程之间切换的开销小。
所处环境:在操作系统中能同时运行多个进程(程序);而在同一个进程(程序)中有多个线程同时执行(通过CPU调度,在每个时间片中只有一个线程执行)
内存分配方面:系统在运行的时候会为每个进程分配不同的内存空间;而对线程而言,除了CPU外,系统不会为线程分配内存(线程所使用的资源来自其所属进程的资源),线程组之间只能共享资源。
包含关系:没有线程的进程可以看做是单线程的,如果一个进程内有多个线程,则执行过程不是一条线的,而是多条线(线程)共同完成的;线程是进程的一部分,所以线程也被称为轻权进程或者轻量级进程。 -
垃圾收集讲一下,1.8有哪些新特性
深入理解JVM垃圾收集机制(JDK1.8)
JDK1.8 十大新特性详解 -
tcp和udp,tcp网络架构
TCP与UDP的对比
TCP/IP架构
TCP/IP五层网络架构及OSI参考模型 -
数组两数之和返回最接近k的值
java中给定整形数组,输出该数组中和数值2最接近的元素
数组-(sum close)找到数组中和与k最接近的3个数字 -
反射了解吗class.forname和classloader区别
在Java的反射中,Class.forName和ClassLoader的区别 -
synchronized和lock的区别
两者区别:
1.首先synchronized是java内置关键字,在jvm层面,Lock是个java类;
2.synchronized无法判断是否获取锁的状态,Lock可以判断是否获取到锁;
3.synchronized会自动释放锁(a 线程执行完同步代码会释放锁 ;b 线程执行过程中发生异常会释放锁),Lock需在finally中手工释放锁(unlock()方法释放锁),否则容易造成线程死锁;
4.用synchronized关键字的两个线程1和线程2,如果当前线程1获得锁,线程2线程等待。如果线程1阻塞,线程2则会一直等待下去,而Lock锁就不一定会等待下去,如果尝试获取不到锁,线程可以不用一直等待就结束了;
5.synchronized的锁可重入、不可中断、非公平,而Lock锁可重入、可判断、可公平(两者皆可)
6.Lock锁适合大量同步的代码的同步问题,synchronized锁适合代码少量的同步问题。
public class Test {
static Object o1 = new Object();
static Object o2 = new Object();
public static void main(String[] args) {
new Thread(new Runnable() {
public void run() {
synchronized (o1) {
System.out.println("线程1锁o1");
try {
Thread.sleep(1000);//让当前线程睡眠,保证让另一线程得到o2,防止这个线程启动一下连续获得o1和o2两个对象的锁。
synchronized (o2) {
System.out.println("线程1锁o2");
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
new Thread(new Runnable() {
public void run() {
synchronized (o2) {
System.out.println("线程2锁o2");
synchronized (o1) {
System.out.println("线程2锁o1");
}
}
}
}).start();
}
}
上面的代码就是一个完整的死锁程序,程序中有两个线程,线程1锁住了o1,获得锁之后休眠1秒钟,这个时候线程2锁住了o2,也进行休眠操作。
线程1休眠完了之后去锁o2,但是o2已经被线程2给锁住了,这边只能等待,同样的道理,线程2休眠完之后也要去锁o1,同样也会等待,这样死锁就产生了。
-
死锁的条件
死锁产生的4个必要条件
1、互斥:某种资源一次只允许一个进程访问,即该资源一旦分配给某个进程,其他进程就不能再访问,直到该进程访问结束。
2、占有且等待:一个进程本身占有资源(一种或多种),同时还有资源未得到满足,正在等待其他进程释放该资源。
3、不可抢占:别人已经占有了某项资源,你不能因为自己也需要该资源,就去把别人的资源抢过来。
4、循环等待:存在一个进程链,使得每个进程都占有下一个进程所需的至少一种资源。
当以上四个条件均满足,必然会造成死锁,发生死锁的进程无法进行下去,它们所持有的资源也无法释放。这样会导致CPU的吞吐量下降。所以死锁情况是会浪费系统资源和影响计算机的使用性能的。那么,解决死锁问题就是相当有必要的了。 -
避免死锁的方法
产生死锁需要四个条件,那么,只要这四个条件中至少有一个条件得不到满足,就不可能发生死锁了。由于互斥条件是非共享资源所必须的,不仅不能改变,还应加以保证,所以,主要是破坏产生死锁的其他三个条件。
a、破坏“占有且等待”条件
方法1:所有的进程在开始运行之前,必须一次性地申请其在整个运行过程中所需要的全部资源。
优点:简单易实施且安全。
缺点:因为某项资源不满足,进程无法启动,而其他已经满足了的资源也不会得到利用,严重降低了资源的利用率,造成资源浪费。
使进程经常发生饥饿现象。
方法2:该方法是对第一种方法的改进,允许进程只获得运行初期需要的资源,便开始运行,在运行过程中逐步释放掉分配到的已经使用完毕的资源,然后再去请求新的资源。这样的话,资源的利用率会得到提高,也会减少进程的饥饿问题。
b、破坏“不可抢占”条件
当一个已经持有了一些资源的进程在提出新的资源请求没有得到满足时,它必须释放已经保持的所有资源,待以后需要使用的时候再重新申请。这就意味着进程已占有的资源会被短暂地释放或者说是被抢占了。
该种方法实现起来比较复杂,且代价也比较大。释放已经保持的资源很有可能会导致进程之前的工作实效等,反复的申请和释放资源会导致进程的执行被无限的推迟,这不仅会延长进程的周转周期,还会影响系统的吞吐量。
c、破坏“循环等待”条件
可以通过定义资源类型的线性顺序来预防,可将每个资源编号,当一个进程占有编号为i的资源时,那么它下一次申请资源只能申请编号大于i的资源。如图所示:
这样虽然避免了循环等待,但是这种方法是比较低效的,资源的执行速度回变慢,并且可能在没有必要的情况下拒绝资源的访问,比如说,进程c想要申请资源1,如果资源1并没有被其他进程占有,此时将它分配个进程c是没有问题的,但是为了避免产生循环等待,该申请会被拒绝,这样就降低了资源的利用率 -
数据库查询时间(优化问题)
1、对查询进行优化,应尽可能避免全表扫描
2、写数据语句时尽可能减少表的全局扫描
3、不要在条件判断时进行 算数运算
4、很多时候用 exists 代替 in 是一个好的选择
浅谈数据库查询优化的几种思路 -
MySQL数据库开发常见问题及几点优化!
库表设计
慢 SQL 问题
误操作、程序 bug 时怎么办 -
字符串常量到底存在哪了?
1、局部变量存储在栈中
2、全局变量、静态变量(全局和局部静态变量)存储在静态存储区
3、new申请的内存是在堆中
4、字符串常量也是存储在静态存储区 -
进程的通信? 管道、共享内存、信号量、消息队列、SOCKET
Linux进程间通信:管道、信号、消息队列、共享内存、信号量、套接字(socket)
Linux线程间通信:互斥量(mutex),信号量,条件变量
Windows进程间通信:管道、消息队列、共享内存、信号量 (semaphore) 、套接字(socket)
Windows线程间通信:互斥量(mutex),信号量(semaphore)、临界区(critical section)、事件(event)
Java进程间通信
传统的进程间通信的方式有大致如下几种:
(1) 管道(PIPE)
(2) 命名管道(FIFO)
(3) 信号量(Semphore)
(4) 消息队列(MessageQueue)
(5) 共享内存(SharedMemory)
(6) Socket
Java如何支持进程间通信。
我们把Java进程理解为JVM进程。很明显,传统的这些大部分技术是无法被我们的应用程序利用了(这些进程间通信都是靠系统调
用来实现的)。但是Java也有很多方法可以进行进程间通信的。 除了上面提到的Socket之外,当然首选的IPC可以使用RMI,另外Java nio的MappedByteBuffer也可以通过内存映射文件来实现进程间通信
17.二叉树的前序遍历和思路?
递归:private void preorder(BinaryNode<T> p) { //根节点 if (p != null) { System.out.print(p.data.toString() + " ");//打印结点数值 preorder(p.left); //打印当前结点的左子树 preorder(p.right); //打印当前结点的右子树 } }
非递归
public void preorderTraverse() {
LinkedStack<BinaryNode<T>> stack = new LinkedStack<BinaryNode<T>>();
BinaryNode<T> p = this.root;
while (p != null || !stack.isEmpty()) {
if (p != null) {
System.out.print(p.data + " "); // 先根遍历
stack.push(p);
p = p.left;
} else {
System.out.print("^ ");
p = stack.pop();
p = p.right;
}
}
}
-
计算机网络中哪些协议用到了栈?
将所有的协议综合起来,各个层次的所有协议被称为协议栈。因特网的协议栈由5个层次组成:物理层、链路层、网络层、传输层和应用层。
HTTP网络协议栈 -
图的最短路径的算法叫什么?
Floyd(弗洛伊德)算法、迪杰斯特拉(Dijkstra)算法 -
链表有使用过吗?讲一下他的优点还有使用场景 //插入最快,查询不快。
单向链表和双向链表的优缺点及使用场景
Java集合List特点及使用场景分析 -
链表和树的区别
链表和树
树是数据结构的一种逻辑结构形式,一个前驱,多个后继
链表是数据结构的一种存储结构形式,用数据域以外的附加存储空间表明逻辑关系
树存储起来,可以用链式存储实现 -
哈希结构和树的区别
哈希表与红黑树的特点及区别
Java中HashMap和TreeMap的区别深入理解
b树和b+树的区别
B树B-树和B+树的总结 -
输入一个链表的头结点,输出当前节点距离最近的,比他大的下一个,要求用O(n)复杂度
找出数组中每个数右边第一个比它大的元素–时间复杂度o(n)单调栈解法
联想面试准备
- 后端应用(主要使用Python/Go/Java语言,框架涉及Django/Gin/Spring
Spring框架 - 熟悉Socket或网络编程技术;熟悉多线程技术,进程间通讯技术;
- Java校招面试题目合集
来源:CSDN
作者:Binrry
链接:https://blog.csdn.net/qq_40859852/article/details/100926663