1.刚才在写wait()的时候提到了sleep(),就说一下二者的区别。
2.既然提到了sleep(),就说一下sleep()和yield()方法有什么区别?
join()方法用法:
3.run()和start()方法的区别?
4.上边多次提到了运行状态,那就来说一下线程的状态流转
总结:线程在给定的时间内只能处于一种状态,这些状态是虚拟机状态,不反映任何 *** 作系统线程状态。
5.提到了线程,就说一下什么是并发和并行。
并发:两个或多个事件在同一时间间隔发生。(就是你这在吃饭你突然来电话了,你就接电话,然后接着去吃饭)
并行:两个或者多个事件在同一时刻发生。(一边打电话一边吃发)
6.既然提到了线程就说一下线程和进程的区别?
进程是程序运行和资源分配的基本单位,一个程序至少有一个进程,一个进程至少有一个线程。进程在执行过程中拥有独立的内存单元,而多个线程共享内存资源,减少切换次数,从而效率更高。线程是进程的一个实体,是cpu调度和分派的基本单位,是比程序更小的能独立运行的基本单位。同一进程中的多个线程之间可以并发执行。
7.创建线程的几种方式
①. 继承Thread类创建线程类
-
定义Thread类的子类,并重写该类的run方法,该run方法的方法体就代表了线程要完成的任务。因此把run()方法称为执行体。
-
创建Thread子类的实例,即创建了线程对象。
-
调用线程对象的start()方法来启动该线程。
②. 通过Runnable接口创建线程类
-
定义runnable接口的实现类,并重写该接口的run()方法,该run()方法的方法体同样是该线程的线程执行体。
-
创建 Runnable实现类的实例,并依此实例作为Thread的target来创建Thread对象,该Thread对象才是真正的线程对象。
-
调用线程对象的start()方法来启动该线程。
③. 通过Callable和Future创建线程
-
创建Callable接口的实现类,并实现call()方法,该call()方法将作为线程执行体,并且有返回值。
-
创建Callable实现类的实例,使用FutureTask类来包装Callable对象,该FutureTask对象封装了该Callable对象的call()方法的返回值。
-
使用FutureTask对象作为Thread对象的target创建并启动新线程。
-
调用FutureTask对象的get()方法来获得子线程执行结束后的返回值。
8.既然提到了Callable,就说一下Runnable和Callable的区别?
Runable:接口中的run()方法的返回值是void,它只是单纯的去执行run()方法中的代码而已.无法判断任务是否被线程池执行成功与否。
Callable:接口中call()方法是有返回值的,是一个泛型,和Future,FutureTask配合可以用来获取异步执行的结果。线程池会 返回一个 future 类型的对象,通过这个 future 对象可以判断任务是否执行成 功,并且可以通过 future 的 get()方法来获取返回值,get()方法会阻塞当前线 程直到任务完成,而使用 get(long timeout,TimeUnit unit) 方法则会阻塞 当前线程一段时间后立即返回,这时候有可能任务没有执行完。
9.synchonized各种加锁场景的作用范围(synchronized可以保证方法或者代码块在运行时,同一时刻只有一个方法可以进入到临界区,同时它还可以保证共享变量的内存可见性。)
作用于静态方法,锁住对象实例(this),每一个对象实例有一个锁
public synchronized void method(){}
作用于Lock.class,锁住的是Lock的Class对象,也是全局只有一个。
synchronized (Lock.Class)
作用于静态方法,锁住的是类Class对象,因为Class的相关数据存储在永久代元空间,元空间是全局共享的,因此静态方法锁相当于类的一个全局锁,会锁住所有调用该方法的线程。
public static synchronized voidmethod(){}
作用于this,锁住的是对象实例,每一个对象实例有一个锁
synchronized (this){}
作用于静态成员变量,锁住的是该静态成员变量对象,由于是静态变量,因此全局只有一个
public static Object monitor=new Objeac(); synchronized(monitor){}
10.提到了Lock就说一下synchronized 与Lock的区别。
11. synchronized和volatile有什么区别?
volatile 关键字是线程同步的轻量级实现,所以 volatile 性能肯定比synchronized 关键字要好synchronized 关键字在 JavaSE1.6 之后进行了主要包括为了减少获得锁和释放锁带来的性能消耗而引 入的偏向锁和轻量级锁以及其它各种优化之后执行效率有了显著提升,实际开发中使用 synchronized 关键字的场景还是更多一些。
12.提到了死锁就说一下什么是死锁
死锁是指两个或两个以上的进程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程。
13.提到了死锁,就说一下如何检测死锁
14.怎么预防死锁?
15.创建线程池有几种方式?
16.线程池的核心属性
17.线程池都有哪种状态?
线程池有五种状态Running、ShutDown、Stop、Tidying、Terminated。
(02) 状态切换:线程池的初始化状态是RUNNING。换句话说,线程池被一旦被创建,就处于RUNNING状态,并且线程池中的任务数为0!
(2) 状态切换:调用线程池的shutdown()接口时,线程池由RUNNING -> SHUTDOWN。
(2) 状态切换:调用线程池的shutdownNow()接口时,线程池由(RUNNING or SHUTDOWN ) -> STOP。
(2) 状态切换:当线程池在SHUTDOWN状态下,阻塞队列为空并且线程池中执行的任务也为空时,就会由 SHUTDOWN -> TIDYING。
当线程池在STOP状态下,线程池中执行的任务为空时,就会由STOP -> TIDYING。
(2) 状态切换:线程池处在TIDYING状态时,执行完terminated()之后,就会由 TIDYING -> TERMINATED。
18.线程池的执行流程(提交任务执行的execute()方法)
19.execute()方法和submit()方法的区别
-
接收的参数不一样
-
submit有返回值,而execute没有
-
submit方便Exception处理
20.线程池有哪些拒绝策略?
AbortPolicy:中止策略。默认的拒绝策略,直接抛出 RejectedExecutionException。调用者可以捕获这个异常,然后根据需求编写自己的处理代码。
DiscardPolicy:抛弃策略。什么都不做,直接抛弃被拒绝的任务。
DiscardOldestPolicy:抛弃最老策略。抛弃阻塞队列中最老的任务,相当于就是队列中下一个将要被执行的任务,然后重新提交被拒绝的任务。如果阻塞队列是一个优先队列,那么“抛弃最旧的”策略将导致抛弃优先级最高的任务,因此最好不要将该策略和优先级队列放在一起使用。
CallerRunsPolicy:调用者运行策略。在调用者线程中执行该任务。该策略实现了一种调节机制,该策略既不会抛弃任务,也不会抛出异常,而是将任务回退到调用者(调用线程池执行任务的主线程),由于执行任务需要一定时间,因此主线程至少在一段时间内不能提交任务,从而使得线程池有时间来处理完正在执行的任务。
21.java中如何保证多线程的线程安全。
线程安全在三个方面体现:
-
原子性:提供互斥访问,同一时刻只能有一个线程对数据进行 *** 作,(atomic,synchronized);
-
可见性:一个线程对主内存的修改可以及时地被其他线程看到,(synchronized,volatile);
-
有序性:一个线程观察其他线程中的指令执行顺序,由于指令重排序,该观察结果一般杂乱无序,(happens-before原则)。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)