以下是我整理的一些面试可能会遇到的一些问题,有需要的可以看看
附上线程的生命周期图:
一.线程与进程
线程:是操作系统能够调度的最小单位,包含在进程中,是进程的实际运作的单位.
进程:简单点就是一个正在进行的程序
区别:线程是进程的子集,一个进程可以有很多个任务,不同的线程执行不同的任务
一个java应用程序至少有两个线程,一个是主线程(main),一个是执行垃圾回收的线程
二.如何在java中实现线程
调用java.lang.Thread类或者实现java.lang.Runnable接口重写run()方法
面试回答上面的就行了,这里写下如何实现的,更能深入记住他
第一种.继承Therad类
public class MyThread extends Thread{
private static int count=1;
public MyThread(String name) {
super(name);
}
public static void main(String[] args) {
MyThread mt1=new MyThread("线程A");
MyThread mt2=new MyThread("线程B");
mt1.start();
mt2.start();
}
public void run() {
for (int i =100; i>0;i--) {
count++;
System.out.println(i+"==="+this.getName());
}
}
第二种 实现Runnable接口
package thread;
public class Demo {
public static void main(String[] args) {
MyRunnable mr = new MyRunnable("线程a");
MyRunnable mr2 = new MyRunnable("线程b");
Thread thread = new Thread(mr);
Thread thread2 = new Thread(mr2);
thread.start();
thread2.start();
}
}
class MyRunnable implements Runnable {
private String name;
public MyRunnable(String name) {
this.name = name;
}
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println(i + "===>" + name);
}
}
}
三.实现线程中的两种方法哪种更好
因为java不支持多重继承但可以一次实现多个接口,所以相对而言 ,实现runnable更好
四.Thread 类中的start() 和 run() 方法有什么区别?
start()是创建一个新的线程,并且在start()内部有run方法,这个可以看源码就能知道.当你调用run
()方法时,只能在原来的线程中调用,但是strat()可以创建新的线程
五.线程安全问题
什么是线程安全?
线程安全就是多个线程同时执行一个任务,造成不一样的运行结果
举个例子,三个窗口同时售票.总共有10张票.a窗口卖了第一张,但是此刻b窗口也在售票,两人同时售票,但是票显示的结果还是9.很明显不对.所以此时需要加一个互斥锁,可以用代码模拟下售票:
public class Tickets {
public static void main(String[] args) {
MyRunnable1 mr1 = new MyRunnable1("窗口a");
Thread thread = new Thread(mr1);
MyRunnable1 mr2 = new MyRunnable1("窗口b");
Thread thread2 = new Thread(mr2);
MyRunnable1 mr3 = new MyRunnable1("窗口c");
Thread thread3 = new Thread(mr3);
thread.start();
thread2.start();
thread3.start();
}
}
class MyRunnable1 implements Runnable {
private String name;
public MyRunnable1(String name) {
this.name = name;
}
static int count = 100;
@Override
public void run() {
while (true) {
synchronized ("a") {
if (count > 1) {
count--;
System.out.println(name + "还剩余" + count);
Thread.yield();
}else {
System.out.println(name+"票已售完");
break;
}
}
}
}
}
六.什么是线程死锁
就是多个线程互相等待,造成多不执行的情况.举个例子,两个中国人进门,两个都很有礼貌,都想等待对方先进才能进,结果最后两个都没进都在等待.还有个就是哲学家问题,4个哲学家围在一起吃饭,中间放一只筷子,然后规定他们只有先取左边的筷子再取右边的筷子才能吃饭.我们来分析筷子作为临界值,当大家都拿起左边的筷子的时候,大家发现右边没筷子了,所以都在希望等对方把筷子放下,然后拿右边的筷子,结果一直僵持着.
所以我们知道造成线程死锁的条件:
(1)互斥条件:一个资源每次只能被一个进程使用。比如:4个哲学界,却只有两双筷子
(2)请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。 比如:他们都不想放下自己手中的筷子
(3)不可剥夺条件:进程已获得的资源,在末使用完之前,不能强行剥夺。 比如:他们都不能取抢夺别人手中的筷子
(4)循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。比如:所以他们之间就形成了循环等待条件
七.sleep()和wait()有什么区别
sleep()是使线程停止一段时间的方法.但在sleep()后不一定立即恢复执行,因为此刻可能别的线程还在争夺赢了cpu使用权,但如果你通过setPriority()方法设置更高的优先权
wait()当线程交互时候,如果线程对同步对象发出wait()调用,这个对象只有在被唤醒才能执行
八.在win32环境中线程有哪三种模式
1.单线程
指从任务的开始到结束都需要自己来完成
2.单元线程
指可以多个单线程组成一个单元,他们完成各自的分工
3.自由线程
这些线程可以互相帮忙执行任务
由于这些是很早之前写的最基础的,后续会将之前整理好的线程高级搬移到博客上