欢迎来到双子树教育网!
机构档案

在线交谈:点击这里给我发消息

咨询热线:159-0741-2407

快速报名,会有咨询师与您联系

学校评价(我要提问/点评)

  • 学校被点评:1
  • 好评(100%)
  • 中评(0%)
  • 差评(0%)

资料认证

    已通过身份证认证 已通过身份证认证

    已通过办学许可认证 已通过办学许可认证

  • 学校浏览人次:
  • 加盟时间:2019年11月15日
动态

JavaSE面试题(十二):多线程(2)

发布者:长沙达内教育 发布时间:2021-01-17 来源:长沙达内教育

Q:多线程的创建方式?

方式一:继承Thread类创建线程类

1 class T extends Thread{2 @Override3 public void run() {45 }6 }

方式二:通过Runnable接口创建线程类

1 class T implements Runnable{2 @Override3 public void run() {45 }6 }

方式三:通过Callable和Future创建线程

1 class T implements Callable{2 @Override3 public String call() throws Exception {4 return null;5 }6 }

达内教育

Q:启动一个线程是调用 run() 方法还是 start() 方法?

启动一个线程是调用start()方法,使线程所代表的虚拟处理机处于可运行状态,这意味着它可以由 JVM 调度并执行,这并不意味着线程就会立即运行。

run()方法是线程启动后要进行回调(callback)的方法。

Q:什么情况下导致线程死锁,遇到线程死锁该怎么解决?

死锁的定义:

死锁是指多个线程因竞争长沙而造成的一种互相等待状态,若无外力作用,这些进程都将无法向前推进。

死锁的条件:

互斥条件:线程要求对所分配的长沙(如打印机)进行排他性控制,即在一段时间内某 长沙仅为一个线程

所占有。此时若有其他线程请求该长沙,则请求线程只能等待。

不剥夺条件:线程所获得的长沙在未使用完毕之前,不能被其他线程强行夺走,即只能由获得该长沙的线程自己来释放(只能是主动释放)。

请求和保持条件:线程已经保持了至少一个长沙,但又提出了新的长沙请求,而该长沙已被其他线程占有,此时请求进程被阻塞,但对自己已获得的长沙保持不放。

循环等待条件:存在一种线程长沙的循环等待链,链中每一个线程已获得的长沙同时被链中下一个线程所请求。即存在一个处于等待状态的线程集合{Pl, P2, …, pn},其中 Pi 等待的长沙被 P(i+1)占有(i=0, 1, …, n-1),Pn 等待的长沙被 P0 占有

循环等待.png

避免死锁:

①加锁顺序(线程按照一定的顺序加锁)

②加锁时限(线程尝试获取锁的时候加上一定的时限,超过时限则放弃对该锁的请求,并释放自己占有的锁)

Q:什么是乐观锁和悲观锁?

悲观锁

Java在JDK1.5之前都是靠synchronized关键字保证同步的,这种通过使用一致的锁定协议来协调对共享状态的访问,可以确保无论哪个线程持有共享变量的锁,都采用独占的方式来访问这些变量。独占锁其实就是一种悲观锁,所以可以说synchronized是悲观锁。

乐观锁

乐观锁(Optimistic Locking)其实是一种思想。相对悲观锁而言,乐观锁假设认为数据一般情况下不会造成冲突,所以在数据进行提交更新的时候,才会正式对数据的冲突与否进行检测,如果发现冲突了,则让返回用户错误的信息,让用户决定如何去做。

Q:乐观锁一定就是好的吗?

乐观锁避免了悲观锁独占对象的现象,同时也提高了并发性能,但它也有缺点:

1.乐观锁只能保证一个共享变量的原子操作。如果多一个或几个变量,乐观锁将变得力不从心,

但互斥锁能轻易解决,不管对象数量多少及对象颗粒度大小。

2.长时间自旋可能导致开销大。假如CAS长时间不成功而一直自旋,会给CPU带来很大的开销。

3.ABA问题。CAS的核心思想是通过比对内存值与预期值是否一样而判断内存值是否被改过,但这个判断逻辑不严谨,假如内存值原来是A,后来被一条线程改为B,最后又被改成了A,则CAS认为此内存值并没有发生改变,但实际上是有被其他线程改过的,这种情况对依赖过程值的情景的运算结果影响很大。

解决的思路是引入版本号,每次变量更新都把版本号加一。

Q:说一下线程池的启动策略?

线程池的执行过程描述:

1/* 2* Proceed in 3 steps: 3* 4* 1. If fewer than corePoolSize threads are running, try to 5* start a new thread with the given command as its first 6* task. The call to addWorker atomically checks runState and 7* workerCount, and so prevents false alarms that would add 8* threads when it shouldn't, by returning false. 9*10* 2. If a task can be successfully queued, then we still eed11* to double-check whether we should have added a thread12* (because existing ones died since last checking) or that13* the pool shut down since entry into this method. So we14* recheck state and if necessary roll back the enqueuing if15* stopped, or start a new thread if there are none.16*17* 3. If we cannot queue task, then we try to add a new18* thread. If it fails, we know we are shut down or saturated19* and so reject the task.20*/

1、线程池刚创建时,里面没有一个线程。任务队列是作为参数传进来的。不过,就算队列里面有任务,线程池也不会马上执行它们。

2、当调用 execute() 方法添加一个任务时,线程池会做如下判断:

①如果正在运行的线程数量小于 corePoolSize,那么马上创建线程运行这个任务;

②如果正在运行的线程数量大于或等于 corePoolSize,那么将这个任务放入队列。

③如果这时候队列满了,而且正在运行的线程数量小于 maximumPoolSize,那么还是要创建线程运行这个任务;

④如果队列满了,而且正在运行的线程数量大于或等于 maximumPoolSize,那么线程池会抛出异常,告

诉调用者“我不能再接受任务了”。

3、当一个线程完成任务时,它会从队列中取下一个任务来执行。

4、当一个线程无事可做,超过一定的时间(keepAliveTime)时,线程池会判断,如果当前运行的线程数大于corePoolSize,那么这个线程就被停掉。所以线程池的所有任务完成后,它最终会收缩到 corePoolSize 的大小。

Q:请说出同步线程及线程调度相关的方法?

wait():使一个线程处于等待(阻塞)状态,并且释放所持有的对象的锁;

sleep():使一个正在运行的线程处于睡眠状态,是一个静态方法,调用此方法要处理 InterruptedException 异常;

notify():唤醒一个处于等待状态的线程,当然在调用此方法的时候,并不能确切的唤醒某一个等待状态的线程,而是由 JVM 确定唤醒哪个线程,而且与优先级无关;

notityAll():唤醒所有处于等待状态的线程,该方法并不是将对象的锁给所有线程,而是让它们竞争,只有获得锁的线程才能进入就绪状态;

注意:java 5 通过 Lock 接口提供了显示的锁机制,Lock 接口中定义了加锁(lock()方法)和解锁(unLock()方法),增强了多线程编程的灵活性及对线程的协调

Q:线程池中的线程是怎么创建的?是一开始就随着线程池的启动创建好的吗?

不是。线程池默认初始化后不启动 Worker,等待有请求时才启动。

当调用 execute方法添加一个任务时,线程池会做如下判断:

如果正在运行的线程数量小于corePoolSize,那么马上创建线程运行这个任务;

如果正在运行的线程数量大于或等于corePoolSize,那么将这个任务放入队列;

如果这时候队列满了,而且正在运行的线程数量小于maximumPoolSize,那么还是要创建非核心线程立刻运行这个任务;

如果队列满了,而且正在运行的线程数量大于或等于maximumPoolSize,那么线程池会抛出异常RejectExecutionException当一个线程完成任务时,它会从队列中取下一个任务来执行。

当一个线程无事可做,超过一定的时间(keepAlive)时,线程池会判断。

如果当前运行的线程数大于 corePoolSize,那么这个线程就被停掉。所以线程池的所有任务完成后,它最终会收缩到 corePoolSize的大小。

以上就是 长沙达内教育 小编为您整理 JavaSE面试题(十二):多线程(2) 的全部内容,更多学习资讯,课程费用,培训时间可咨询在线老师!
校区地址
  • 乘车路线:电话预约
  • 授课地址:

地理位置 Location