线程和进程有什么区别?
进程就是一个程序,比如QQ.微信,将代码加载到内存中
线程,一个进程有一个或多个线程,比如,QQ中打开照片,发送消息就是不同的线程的操作,使用多线程可以使程序效率更高
并发和并行有什么区别?
并发就是一个CPU,当我们开启多个线程的时候,程序是按照指令执行的,执行完这个线程指令,在执行另一个线程的指令,微观上是串行的,但是感觉是并行的
并行,是多个CPU,每个核都可以运行指令,都可以运行线程,这个就是并发执行的
线程创建4种方式?
1.new Thread()创建线程,重回里面的run()方法,调用start方法来开启线程
2.实现Runnable()接口,重回里面的run方法来创建线程,将实现类传递到Thred的构造参数中,调用start方法开启线程
3.创建FutureTask对象,构造参数中传递Callable接口实现类,Callable接口重回call()方法,将FutureTask对象传递到Thread的构造参数中,调用start方法开启线程
4.使用线程池开启线程
线程有哪些状态
NEW 新建状态 就是new Thread()
RUNNABLE 执行状态
TIME_WAITING 计时等待状态,使用sleep方法进行休眠
WAITING 等待状态,使用wait()方法
BLOCKED 阻塞状态,没有获取到锁
TERMINATED 结束状态
为什么要使用线程池?
使用线程池可以减少线程的创建和销毁,可以提高效率,可以重复利用线程对象
可以调整工作线程数目,减少内存的消耗
线程池的构造方法里几个参数的作用分别都是什么?
线程池中有7个参数
第一个参数是核心线程数量
第二个参数是最大核心线程数量 最大核心数量=核心线程数量+救急线程数量
第三个参数是救济线程数量的存活时间
第四个参数是救济线程的时间单位
第五个参数是线程队列,当等待的线程存放队列中,等线程空闲了,在执行
第六个参数是线程的创建方式,是通过那些方式来创建线程
第七个参数是线程的拒绝策略,当队列也太多任务时,执行策略
线程池流程
向线程池中添加任务,线程池中核心线程会执行任务,当任务队列满了之后,就会让救济线程去处理任务,如果救济线程也无法创建线程,就会触发拒绝策略来处理线程
线程池拒绝策略有哪些
丢弃任务直接抛出异常 AbortPolicy
丢弃任务不抛出异常 DiscardPolicy
抛弃队列中等待时间最久的,将当前任务加入 DiscardOldestPolicy
调用任务的run方法绕过线程 池,让调用者执行 CallerRunPolicy
notify()和 notifyAll()有什么区别?
notify()方法唤醒线程等待区中的随机的一个线程
notifyAll()方法唤醒线程等待区中的所有线程
wait()和sleep()的区别
相同点:wait()和sleep()都可以让线程等待,暂时放弃CPU的使用
不同点: wait()方法是Object的方法,每一个对象都有这个方法,而sleep()方法是Thread类的静态方法
wait()使用必须是锁的对象调用,不然会报错,不会拿着锁睡觉,其他线程是可以获得锁对象的
sleep()在synchronized中会拿着锁睡觉,其他线程是拿不到锁对象的
wait()和wait(long)可以被notify唤醒,wait()如果不唤醒就会一直等下去,执行sleep(long)和wait(long)线程都会在等待相应的毫秒后会唤醒,它们都可以被打断唤醒
volatile能否保证线程安全
不可以保证线程是安全的,volatile只保证了线程的可见性和有序性,没有保证原子性
可见性: 属性改变,其他线程也是知道这个属性改变
有序性: 不会进行指令重排,会按照代码的编写顺序进行执行
原子性:线程正在执行一段代码,执行过程中间是不可以被打断的
lock锁和synchronized锁区别
synchronized是java的关键字,lock是接口,我们可以使用它的实现类实现锁的功能
synchronized代码块锁的是它里面的对象,这个对象必须唯一,才会同步,synchronized方法锁的是this,锁的是创建这个类的对象,synchronized静态方法锁的是Class,synchronized我们不用去管是怎么加锁,释放锁,会自动执行
Lock锁使用lock方法来加锁,用unlock来释放锁,我们应该把释放锁放到finally中,如果锁使用不当,没有释放锁,会造成死锁问题