【面试题1】
byte b1=3,b2=4,b;
b=b1+b2;//这个是类型提升,所以有问题
//因为变量相加,会首先看类型问题,最终把结果赋值的也会考虑类型问题
b=3+4;//是没有问题的,我做错了,常量,先把结果计算出来,然后看是否在byte
//的范围内,如果在就不报错。
哪句是编译失败的呢?为什么呢?
【思考题】
byte b=130;有没有问题?如果我想让赋值正确,可以怎么做?结果是多少呢?
//因为byte的范围是:-128到127.
//而130不在此范围内,所以报错。
//所以我们可以使用强制类型转换,关键是结果
/*
分析过程:
我们要想知道结果是什么,就应该知道是如何进行计算的。
而我们又知道计算机中数据的运算都是补码进行的。
而要得到补码,首先要计算出数据的二进制。
A:获取130这个数据的二进制。
00000000 00000000 00000000 1000 0010
这是130的原码,也是反码,还是补码
B:做截取操作,截成byte类型的了。
1000 0010
这个结果是补码
C:已知补码求原码
符号位数值位
补码:10000010
反码:10000001
原码:11111110
*/
练习:byte b=300;
多线程
【面试题2】:run()和start()的区别
run():仅仅是封装被线程执行的代码,直接调用普通方法
start():首先启动了线程,然后再由JVM去调用该线程的run()方法
【面试题3】
线程的生命周期图解?
新建:创建线程对象
就绪:有执行资格,没有执行权
运行:有执行资格,有执行权
阻塞:由于一些操作让线程处于了该状态。没有执行资格,没有执行权
而另一些操作却可以把它给激活,激活后处于就绪状态。
死亡:线程对象变成垃圾,等待被回收
====================================================
【写一个死锁的代码】
//程序相互等待
public class MyLock{
//创建两把锁对象
public static final Object objA=new Object();
public static final Object objB=new Object();
}
public class DieLock extends Thread{
private boolean flag;
public DieLock(boolean flag){
this.flag=flag;
}
@Override
public void run(){
if(flag){
synchronized(MyLock.objA){
System.out.println("if objA");
synchronized (MyLock.objB){
System.out.println("if objB");
}
}
}else{
synchronized(MyLock.objB){
System.out.println("else objB");
synchronized (MyLock.objA){
System.out.println("else objA");
}
}
}
}
}
public class DieLockDemo{
main(){
DieLock dl1=new DieLock(true);
DieLock dl2=new DieLock(false);
dl1.start();
dl2.start();
}
}
===========================================================================
【面试题4】
public class ThreadDemo{
main(){
//继承Thread类来实现多线程
new Thread(){
public void run(){
for(int x=0;x<100;x++){
System.out.println(Thread.currentThread().getName()+":"+x);
}
}
}.start();
//实现Runnable接口来实现多线程
new Thread(new Runnable(){
@Override
public void run(){
for(int x=0;x<100;x++){
System.out.println(Thread.currentThread().getName()+":"+);
}
}
}){}.start();
//更有难度的
new Thread(new Runnable(){
@Override
public void run(){
for(int x=0;x<100;x++){
System.out.println("hello"+":"+);
}
}
}){
public void run(){
for(int x=0;x<100;x++){
System.out.println("world"+":"+);
}
}
}.start();//面试的时候会问报错吗?不会,打印world
}
}
【多线程面试题5】
1;多线程有几种实现方案,分别是哪几种?【别答三种】【掌握情况】
继承Thread类
实现Runnable接口
扩展:实现Callable接口。这个得和线程池结合
2;同步有几种方式,分别是什么?
两种。
同步代码块
同步方法
3;启动一个线程是run()还是start()?它们的区别?
start().
run():封装了被线程执行的代码,直接调用仅仅是普通方法的调用
start():启动线程,并由JVM自动调用run()方法
4;sleep()和wait()方法的区别?
sleep():必须指时间;不释放锁
wait():可以不指定时间,也可以指定时间;释放锁
5;为什么wait(),notify(),notifyAll()等方法都定义在Object类中?
因为这些方法的调用是依赖于锁对象的,而同步代码块的锁对象是任意锁。
而Object代表任意的对象,所以,定义在这里面。
6;线程的生命周期图
新建--就绪--运行--死亡
新建--就绪--运行--阻塞--就绪--运行--死亡
建议:画图解释
【面试题6】
单例模式的思想是什么?请写一个代码体现。【保证类在内存中只有一个对象,这个就是单例模式的思想 】
开发:饿汉式【是一种不会出问题的单例模式】
面试:懒汉式【可能会出问题的单例模式】
A:懒加载(延迟加载)【用的时候才去加载】
B:线程安全问题:
a:是否多线程环境是
b:是否有共享数据是
c:是否有多条语句操作共享数据是
单例模式:【单例设计模式:单例模式就是要确保类在内存中只有一个对象,该实例必须自动创建,并且对外提供】
【优点:在系统内存中只存在一个对象,因此可以节约系统资源,对于一些需要频繁创建和销毁的对象,单例模式
无疑提高了系统的性能。】
【缺点:没有抽象层,因此扩展很难。
职责过重,在一定程序上违背了单一职责。】
饿汉式:类一加载就创建对象
懒汉式:用的时候,才去创建对象
【饿汉式】
public class Student{
//构造私有
private Student(){}
//自己造一个
//静态方法只能访问静态成员变量
//为了不让外界直接访问修改这个值,加private
private static Student s=new Student();
//提供公共的访问方式
//为了保证外界能够直接使用该方法,加静态
public static Student getStudent(){
return s;
}
}
public class StudentDemo{
main(){
//通过单例如何得到对象呢?
//Student s=null;//因为在Student中加了private,所以这里会报错,
Student s1=Student.getStudent();
Student s2=Student.getStudent();
System.out.println(s1==s2);//true
System.out.println(s1);//null,被加了private后,这里就不显示null了,下面也是
System.out.println(s2);//null
}
}
=================================================
【懒汉式】
public class Teacher{
private Teacher(){}
private static Teacher t=null;//后面new的话,就是饿汉式
//public static Teacher getTeacher(){
public synchronized static Teacher getTeacher(){//面试的时候写这个才是正确的
if(t==null){//在这里多个线程抢
t=new Teacher();
}
return t;
}
}
public class TeacherDemo{
public static void main(String[] args){
Teacher t1=Teacher.getTeacher();
Teacher t2=Teacher.getTeacher();
System.out.println(t1==t2);//true,第一次造了一下
System.out.println(t1);//不是null
System.out.println(t2);//不是null
}
}
本文为头条号作者发布,不代表今日头条立场。