1、线程和进程的区别
进程是线程的集合,线程是进程中的一条执行路径。比如我们拿QQ为例,那么QQ就是一个进程,而聊天、传输任务等就是多个线程。
2、为什么要使用多线程
充分利用CPU的空余时间
3、多线程的创建方式
第一种:继承thread类,重写run方法
第二种:实现Runable接口,重写run方法
第三种:使用匿名方式
第四种:使用线程池创建线程
4、创建线程,使用继承thread类好还是实现Runnable接口好,为什么
创建线程,实现Runnable接口好,因为Java只支持单继承,实现了Runnable接口,还可以继承其他类
5、线程启动,是通过调用start()方法,还是调用run()方法,为什么
线程启动,是通过调用start()方法,这样才会启动新的线程,调用run方法,不会启动新的线程,程序变成同步执行的方式
6、线程对象常用的api有哪些,举例一下
start():启动新的线程
currentThread():获取当前线程
getId():获取线程的id
getName():获取线程的名字
sleep(long mill):使线程休眠
Stop():使线程停止,暴力停止,这个方式已经放弃,建议不要使用
线程常用的构造函数:
Thread()
Thread(String name)
Thread(Runnable r)
Thread(Runnable r,String name)
7、守护线程
守护线程就是为用户自定义的线程服务的线程,比如说Gc线程
Java中有两种线程:一种是用户线程(就是用户自定义的线程),另一种就是守护线程(就是服务用户线程的线程),守护线程不用我们管理,它是跟着用户线程的生命周期而行的,只要用户线程消亡了,守护线程也就自动消亡被系统回收
将用户线程变为守护线程的方式:通过setDaeon(true),就可以设置为守护线程
8、什么是线程的生命周期
就是一个线程从新建到死亡的过程,从生到死
线程的生命周期经历五个状态:
新建状态 就绪状态 阻塞状态 运行状态 死亡状态
新建状态:就是使用了new关键字,新建一个线程的时候
就绪状态:就是这个线程调用了start()方法,CPU准备各种资源
阻塞状态:就是线程已经处于就绪状态或者已经在运行,但遇到了sleep方法,主动让出CPU的执行资源,从而停止自己的任务,这就是线程的阻塞状态
运行状态:就是线程已经在执行run方法里面的内容
死亡状态:这个时候分两种情况:第一种就是run方法正常执行完之后,线程正常死亡
另一种就是:线程遇到了异常而被迫停止,这种就是线程的意外死亡
9、join方法有什么作用
让其他的线程等待,使调用这个方法的线程优先执行,只有这个调用方法的线程执行完之后,才能让其他线程执行
10、什么是线程的优先级,你知道吗,请简要描述一下
线程的优先级就是线程获得CPU处理资源的多少,用一个int类型的priority来表示线程的优先级,分为1-10,10个级别,字数越小,表示线程的优先级越高,但是并不是线程的优先级越高,他不一定会优先执行,只是它获取CPU的处理资源概率比较大,通过setPriority(数字)可以设置线程的优先级
11、你在哪个场景使用到了多线程,为什么要使用多线程
因为使用多线程可以提高程序的执行效率
分批次发送短信使用到了多线程,在一个商城搞活动,通知给用户,发送短信通知给每一个用户
12、什么是线程安全问题
线程安全问题,就是多个线程访问同一个对象的同一个实例变量或全局静态变量的时候,在做写的操作时,会发生值不同步、数据不一致的问题,这就是线程安全问题,在做读的操作时不会发生线程安全问题。
13、如何解决多线程之间线程安全问题?
使用同步synchronized或者使用锁
14、为什么使用线程同步或使用锁能解决线程安全问题呢?
使用线程同步或者使用锁,那么就只能让一个线程去操作实例变量,其他的线程等待这个线程操作完毕之后,才会进行执行。这样就解决了线程安全的问题
15、什么是多线程之间同步?
多线程之间同步,就是一个线程在进行操作的时候,不会受到其他线程的干扰
16、什么是同步代码块?同步代码块使用的锁
同步代码块就是将可能会发生线程安全问题的代码,使用synchronized代码块包裹起来,使只有获得锁的线程执行,从而解决线程安全问题。 同步代码块使用的是对象锁。
17、什么是同步函数?同步函数使用的是什么锁,如何证明
同步函数就是方法使用synchronized,同步函数使用的是this明锁。证明同步函数使用的是this锁。那么就以 抢票为例,一部分抢票使用同步代码块,使用this明锁,一部分使用同步函数,如果抢票一致,那么就证明同步函数使用的是this锁,如果抢票不一致,证明使用的不是this锁,事实证明,同步函数使用的是this锁
18、什么是静态同步函数?使用的是什么锁
静态同步函数,就是静态方法上加上synchronized关键字,静态同步函数使用的是类.class,文件作为锁
19、什么是多线程死锁?
多线程死锁就是同步中嵌套同步,举个例子,一个方法a执行的时候有自己的锁,同时执行下去又要用到方法b的锁,同样方法b有自己的锁,执行下去又要用到方法a的锁,那么在多线程的情况下,就会出现你要我的锁我要你的锁,从而造成死锁的现象。
20、多线程有哪三大特性
原子性:一个操作或者多个操作,要么全部成功,要么全部失败,这个就是线程的原子性,跟关系型数据库的原子性相似
可见性:就是一个线程的操作结果,对其他线程是可见的
有序性:就是线程在操作结果来说是有序的,你结果是如何,可能代码的书写顺序和执行顺序不一样,但是执行结果一样的。但是在高并发情况下,指令重排的发生,可能会出现意想不到的结果,但是这种情况发生的概率是很小的,但是一旦发生就会出现严重的后果,可以使用volatile关键字禁止指令重排
21、Java内存模型
Java 的内存模型,就是jmm,规定一个线程的操作结果对于其他线程来说是可见的。这是一个抽象的概念,共享变量放在主内存中,每个线程为了效率,在本地自己维护了一个本地内存,线程每次读写的时候,都只到自己的本地内存中读写,不到主内存,这就造成可见性的问题,可以使用volatile解决。
22、什么是Volatile?Volatile的作用是什么?
Volatile关键字就是为了解决数据可见性的问题。它的作用就是使数据在多个线程之间可见,第二个作用就是禁止指令重排
23、解释一下什么是AtomicInteger原子类
AtomicInteger原子类是线程安全的类,它的没法操作是线程安全的,但是规定了每次加减的时候是线程安全,如果又定义加减的数量,那么这个操作就不是线程安全的了
24、volatile与synchronized区别
Volatile关键字是轻量级的,只可以修饰在变量中,而synchronized是重量级的,不仅可以放在变量中修饰,还可以放在方法中
volatile保证线程的可见性,而synchronized是保证线程的原子性
Volatile修饰变量的时候是非阻塞,而synchronized是阻塞的,因为多个线程会等在那里去竞争锁
25、为什么说synchronized关键字保证原子性,又能保证数据的可见性呢
这里我们来说,synchronized关键字限定只有一个线程对数据进行修改,这样就保证原子性,同样,由于jmm(Java的内存模型)我们知道有主内存和线程的内地内存,synchronized关键字都强制线程去主内存中读取数据,数据是从主内存中拿到的,对于每个线程来说都是一样的,从而间接保证可见性。
26、什么是ThreadLocal,实现的原理是什么
threadLocal就是为了提高效率,允许每个threadlocal拥有自己独立的局部变量,threadlocal是通过ThreadLoca通过map集合实现的
27、什么是多线程间的通信
多线程通讯就是多个线程操作同一个对象的共享变量,需要把自己的操作结果,通知给其他线程,让其他的线程知道你做了什么
28、Wait/notify/notifyall
相同点:Wait、notify、notifyall都是object中的方法,底层都是调用jvm里面的native方法,它们都是对要有同一把锁进行操作的,不然会报错
不同点:Wait方法就是放弃线程持有的锁和执行资源,进入线程的等待池等待
Notify:唤醒监控同一把锁的线程
Notifyall:唤醒监控这把锁的所有线程
29、wait和sleep的区别
相同点:都能线程停止正在执行的任务
不同点:wait方法是属于object里面的,调用wait方法的线程会放弃持有的锁(既放弃执行资源,又放弃锁)
Sleep方法是thread类里面的,调用sleep方法的线程是不会放弃所持有的的锁,只是休眠时间过了,那么右继续执行(只放弃执行资源,不放弃锁)
30、什么是JDK1.5-Lock
Lock是jdk1.5新增的,类似于synchronized解决线程安全问题
31、Lock的写法
Lock lock= new ReentrantLock();
lock.lock(); //加锁
try{
//将可能会出现线程安全的代码放在里面
}finally{
lock.unlock();//一定要解锁,防止死锁的发生
}
32、Lock和synchronized的区别
相同点:都能解决线程安全问题
不同点:lock是非阻塞的,各个线程在规定的时间获取锁,获取到才执行加锁里面的内容,时间过期以后不再尝试重新获取锁。Lock是手动获取锁和解锁的,所以要把解锁的操作一定要放在finally中。
Synchronized是阻塞的,多个线程会去竞争这把锁,而且synchronized是自动的,自动获取锁和解锁
33、Condition写法,作用是什么
类似于线程通信的方法,写法是:
Lock lock= new ReentrantLock();
Condition condition = lock.newCondition();
res. condition.await(); 类似wait
res. Condition. Signal() 类似notify
34、如何停止线程
有两种,一种是异常停止,一种是正常停止
正常停止就是:线程执行完run方法里面的内容
异常停止:就是使用中断标志interrupt,检测到中断标志以后,抛出异常