我走的是JavaEE企业版的开发,目前大三在读,路线也是先学的 c语言、java、HTML+CSS3、Jquery、python等 之后专注于 java 走后端开发路线学了MySQL、JavaWeb、SSM、目前学校还在教Springboot
但我感觉进度太慢了,自学了Springboot、Git、MP、SpringCloud(在学)、Linux(再学)、dubbo+zookeeper等一些知识点,然后把JavaSE、MySQL复习了一遍、目前还在复习Java多线程的知识点
为什么给大家说我学的路线和进度呢 ,因为我做笔试的时候就发现了一个很大的问题,我选错职位了,只看见了招Java的就去了,报的是移动开发(Android或者IOS),做题那叫一个懵逼啊,还好有java基础题、数据结构设计、计算机网络、操作系统等题还看得懂,但还是懵逼的很,还有三道算法,做了两个小时,也不知道做了啥,交上去就感觉无了,但就这样神奇的通过了笔试,虽然我不知道是怎么过的,但大家千万不要妄自菲薄,虽然自己不咋地,但同届的又有多强呢,有职位就投,但还是得看看自己对口的是什么,不然过了笔试,面试也会懵逼。
这里我说一下,百度发面试通知的时候,会有个链接,点进去后选择自己希望面试的时间,这里大家尽力早的选择,我因为想跟辅导员了解一下面试过程就点晚了,提示我当前面试页面显示的这些时间段人满了(链接里没有任何hr的联系方式),这就搞得我更懵逼了,给面试机会不让面试,这不是耍猴吗,但当时时间还早,距离面试还有两天,我当晚去笔试了另一家银行后,在进入页面,就有其他的时间段了,所以遇事不要慌,是等等党的胜利(但工作这事你不上,别人就上了,我特指没办法的是,不要让慌张让你紊乱,该干啥干啥)
我约的四点的面试,三点半我想试试可以联线吗,一点排队,面试官秒接,然后面试就开始了,面试官一上来找我要了一份简历,看了之后说,你学的与我们招的不对口还需要继续吗?(虽然面试官态度真的很好,但对我是暴击),所以投简历的时候一点要看职位与专业对不对口,我就硬着头皮说“我可以学,可以继续面试吗”(我也不想错过这第一次面试的机会),面试官会根据你的情况出题,所以没有问我关于Android相关的问题
我介绍了我自己和做项目的经历(这里可以挖些坑,比如你用了什么方法,不细讲,如果运气好,下一个问题或许会问,这样你可以根据自己学的高谈阔论)
自己挖的坑自己填,然后不要弄些假项目,不然不好说
这个跟java无关,就略了
(1) 竞争与原子操作
多线程同时访问和修改同一个数据时,可能存在风险,数据不能保证我们得到的预期数据,解决的办法,我们可以采用原理类,比如JAVA 本身提供了很多的原子类,AtomicInteger ,AtomicLong 等常见的基本数据类型的原子包装类定义,实现数据安全。
(2) 同步与锁
多线程中我们定于的数据,使用Lock去保证数据操作的过程中只有一个线程进入,这个线程拿到锁后,其他线程都不能拿到该锁,进而保证数据的可靠性。
(3) 可重入
一个函数被重入,表示这个函数没有执行完成,但由于外部因素或内部因素,又一次进入该函数执行。例如单片机、处理器的中断会出现重入现象。
参考文章:函数可重入性(Reentrancy)概念详解_Smith先生的博客-CSDN博客_可重入性
(4) 过度优化
即使使用了合理使用锁,也不一定保证了线程安全,因此需要进行代码的二次优化,使用volatile关键字试图阻止过度优化,它可以做两件事:第一,阻止编译器为了提高速度将一个变量缓存到寄存器而不写回;第二,阻止编译器调整操作volatile变量的指令顺序。
参考文章:确保线程安全的几种方法_周兆熊的博客-CSDN博客_确保线程安全的几种方法
1、synchronized方式(重量级锁)
加锁方式:synchronized(object)传入对象,不同对象代表不同锁,可以在线程外部新建对象。
2、Lock(比synchronized要轻量级)
3、wait() notify() notifyAll()
wait() notify() notifyAll() 是Object上的方法,只有Object是对象监视器时候才能调用此方法
所以简历里信息的一定真实
MVC(Model View Controller)是软件工程中的一种软件架构模式,它把软件系统分为模型、视图和控制器三个基本部分。用一种业务逻辑、数据、界面显示分离的方法组织代码,将业务逻辑聚集到一个部件里面,在改进和个性化定制界面及用户交互的同时,不需要重新编写业务逻辑。
M:Model,模型。 JavaBean
V:view视图。JSP、HTML等来进行数据展示
C:Controller控制器。 Servlet
获取View的请求
调用模型将数据交给视图进行展示
控制器Controller
的作用就是将Model
与 View
一一对应起来
我们用用户登录这个例子来说明:
View层是 index.jsp
,Cotroller是 /loginServlet
,Model是 JavaBean(pojo)
对象
用户看到的是JSP展示页面,用户输入数据点击登录按钮时,这是JSP会通过数据共享将请求转发到/loginServlet
控制器上
然后控制器再将请求分发到Model上,通过JDBC连接到数据库来查询数据库中是否存在该用户信息。
若存在该用户,则返回信息,让控制器告诉前台页面展示登陆成功的信息;不存在则告诉登陆失败…
View来响应控制器交给它的数据
在这个过程中,控制器其实只是起到了承上启下的作用,它只负责中转(指挥调度),不负责具体的业务操作。
MVVM是Model-View-ViewModel的简写。它本质上就是MVC 的改进版,整体和mvc差不多,最大的区别就是mvc是单向的,而mvvm是双向的,并且是自动的,也就是数据发生变化自动同步视图,视图发生变化自动同步数据,同时解决了 mvc 中大量的 DOM 操作使页面渲染性能降低,加载速度变慢,影响用户体验。和当 Model 频繁发生变化,开发者需要主动更新到 View
import java.util.Stack;
public class Solution {
public ListNode ReverseList(ListNode head) {
Stack stack= new Stack<>();
//把链表节点全部摘掉放到栈中
while (head != null) {
stack.push(head);
head = head.next;
}
if (stack.isEmpty())
return null;
ListNode node = stack.pop();
ListNode dummy = node;
//栈中的结点全部出栈,然后重新连成一个新的链表
while (!stack.isEmpty()) {
ListNode tempNode = stack.pop();
node.next = tempNode;
node = node.next;
}
//最后一个结点就是反转前的头结点,一定要让他的next
//等于空,否则会构成环
node.next = null;
return dummy;
}
}
public ListNode ReverseList(ListNode head) {
//新链表
ListNode newHead = null;
while (head != null) {
//先保存访问的节点的下一个节点,保存起来
//留着下一步访问的
ListNode temp = head.next;
//每次访问的原链表节点都会成为新链表的头结点,
//其实就是把新链表挂到访问的原链表节点的
//后面就行了
head.next = newHead;
//更新新链表
newHead = head;
//重新赋值,继续访问
head = temp;
}
//返回新链表
return newHead;
}
/**
* struct TreeNode {
* int val;
* struct TreeNode *left;
* struct TreeNode *right;
* };
*/
class Solution {
public:
/**
*
* @param root TreeNode类
* @return int整型vector>
*/
//前序遍历模板;
void f(TreeNode* root,int level,vector> &res){
if(!root)return ;
if(level>=res.size()){//最新的深度,申请一个数组存储;
res.push_back(vector {});
}
res[level].push_back(root->val);
f(root->left,level+1,res);//遍历左子树;
f(root->right,level+1,res);//遍历右子树;
}
vector > levelOrder(TreeNode* root) {
// write code here
vector> res;//存储最终结果;
f(root,0,res);//前序遍历;
return res;//返回结果;
}
};
/**
* struct TreeNode {
* int val;
* struct TreeNode *left;
* struct TreeNode *right;
* };
*/
class Solution {
public:
/**
*
* @param root TreeNode类
* @return int整型vector>
*/
vector > levelOrder(TreeNode* root) {
// write code here
vector > vv;
if(!root){
return vv;//二叉树为空
}
queue qq;//队列存放相邻两层节点;
qq.push(root);
while(!qq.empty()){
vector tempv;
int size=qq.size();
for(int i=0;ival);
//将下一层的节点入队;
if(tt->left)qq.push(tt->left);
if(tt->right)qq.push(tt->right);
}
vv.push_back(tempv);//加入将要返回的数组中;
}
return vv;//返回最终结果
}
};