Java多线程基础Q&A
2021-08-28 10:20:33 63 举报
AI智能生成
登录查看完整内容
Java多线程基础Q&A
作者其他创作
大纲/内容
Q: Thread的deprecated过期方法是哪3个?作用是啥?A: stop(), 终止线程的执行。 suspend(), 暂停线程执行。 resume(), 恢复线程执行。
Q: 废弃stop的原因是啥?A: 调用stop时,会直接终止线程并释放线程上已锁定的锁。线程内部无法感知,并且不会做线程内的catch操作!就像一个不会负责的渣男。
Q: stop的替代方法是什么?A: interrupt()。调用thread.interrupt()终止时, 不会直接释放锁,会把线程的状态改变, 标记为中断。然后线程的一些方法可以根据当前线程状态进行对应的操作,例如Tread.sleep()会抛出interrupException错误。但是业务代码中如果没有对线程状态进行监控,那么这并不会影响业务代码的继续运行。
font color=\"#f57f17\
Q: suspend/resume的废弃原因是什么?A: :调用suspend不会释放锁。如果线程A暂停后,他的resume是由线程B来调用的,但是线程B又依赖A里的某个锁,那么就死锁了。
Q: Thread.sleep()和Object.wait()的区别A:sleep不会释放对象锁, 而wait会释放对象锁。
Q:Runnable接口和Callable的区别。A: Callable可以和Futrue配合,并且启动线程时用的时call,能够拿到线程结束后的返回值,call方法还能抛出异常。
Q: 线程A如下: public class A extends Thread { @Override public void run() { System.out.println(\"this.isAlive()=\" + this.isAlive()); } } //把线程A作为构造参数,传给线程B A a = new A(); Thread b = new Thread(a); b.start()此时会打印什么?A:此时会打印false! 因为把a作为构造参数传入b中, b执行start时, 实际上是在B线程中去调用了 A对象的run方法,而不是启用了A线程。
Q: 线程的6种状态是:A:New: 新建了线程,但是还没调用startRUNNABLE: 运行, 就绪状态包括在运行态中BLOCKED: 阻塞,一般是因为想拿锁拿不到WAITING: 等待,一般是wait或者join之后TIMED_WAITING: 定时等待,即固定时间后可返回,一般是调用sleep或者wait(时间)的。TERMINATED: 终止状态。
Thread类基础
即可修饰代码块, 也可修饰方法体:修饰普通方法 -> 对象锁修饰静态方法 -> 类锁
Q: 调用下面的f()时,会出现死锁吗?class A{ synchroized f(){ t() } synchroized t(){ }}A:不会。1个线程内, 可以重复进入1个对象的synchroized 块。原理:当线程请求自己的锁时。JVM会记下锁的持有者,并且给这个锁计数为1。如果该线程再次请求自己的锁,则可以再次进入,计数为2.退出时计数-1. 直到全部退出时才会释放锁
Q: 2个线程同时调用f1和f2会产生同步吗?class A{ private static synchronized void f1(){}; private synchronized void f2(){};}A:不会产生同步。二者不是1个锁。f1是类锁,等同于synchronized(A.class)f2是对象锁。
synchronized关键字
final CountDownLatch latch = new CountDownLatch(2);// 2是计数器初始值
初始化, 然后执行latch.await()时, 就会阻塞,直到其他线程中把这个latch进行latch.countDown(),并且计数器降低至0。
和join的区别:join阻塞时,是只等待单个线程的完成而CountDownLatch可能是为了等待多个线程
Q: countDownLatch的内部计数值能被重置吗?A: 不能重置了。如果要重新计数必须重新new一个。毕竟他的类名就叫DownLatch
CountDownLatch
FutureTask<Integer> task = new FutureTask<>(runable);
可以理解为一个支持有返回值的线程,当调用task.get()时,就能能达到线程里的返回值
Q:调用futrueTask.get()时,这个是阻塞方法吗?如果是阻塞,什么时候会结束?A:是阻塞方法。线程跑完并返回结果阻塞时间达到futrueTask.get(xxx)里设定的xxx时间线程出现异常InterruptedException或者ExecutionException线程被取消,抛出CancellationException
FutureTask
用Semaphore(permits)构造一个包含permits个资源的信号量然后某线程做消费动作, 则执行semaphore.acquire(),则会消费一个资源如果某线程做生产动作,则执行semaphore.release(),则会释放一个资源(即新增一个资源)
Semaphore
栅栏,一般是在线程中去调用的它的构造需要指定1个线程数量,和栅栏被破坏前要执行的操作每当有1个线程调用barrier.await(),就会进入阻塞,同时barrier里的线程计数-1。当线程计数为0时, 调用栅栏里指定的那个操作后,然后破坏栅栏, 所有被阻塞在await上的线程继续往下走。
CyclicBarrier
两方栅栏,用于交换数据。简单说就是一个线程在完成一定的事务后,想与另一个线程交换数据则第一个先拿出数据的线程会一直等待第二个线程,直到第二个线程拿着数据到来时才能彼此交换对应数据
Exchanger
其他的同步工具
Q: 线程池的keepalive参数是干嘛的?A:当线程数量在corePoolSize到maxinumPoolSize之间时, 如果有线程已跑完,且空闲时间超过keepalive时,则会被清除(注意只限于corePoolSize到maxinumPoolsize之间的线程)
Q: 线程池有哪三种队列策略?A:握手队列线程数量不做限制。可能造成线程数量无限增长直到超过maxinumPoolSize(相当于corePoolSize没什么用了,只以maxinumPoolSize做上限)无界队列等待队列长度不做限制,即线程数量达到corePoolSize时,后面的线程只会在队列中等待。(相当于maxinumPoolSize没什么用了)有界队列
Q: submit和execute的区别是什么?A: execute只能接收Runnable类型的任务,而submit除了Runnable,还能接收Callable(Callable类型任务支持返回值) execute方法返回void, submit方法返回FutureTask。异常方面, submit方法因为返回了futureTask对象,而当进行future.get()时,会把线程中的异常抛出,因此调用者可以方便地处理异常。(如果是execute,只能用内部捕捉或者设置catchHandler)
Q:线程池中, shutdown、 shutdownNow、awaitTermination的区别?A:shutdown: 停止接收新任务,等待所有池中已存在任务完成( 包括等待队列中的线程 )。异步方法,即调用后马上返回。shutdownNow: 停止接收新任务,并 停止所有正执行的task,返回还在队列中的task列表 。awaitTermination: 仅仅是一个判断方法,判断当前线程池任务是否全部结束。一般用在shutdown后面,因为shutdown是异步方法,你需要阻塞等待什么时候才真正结束。
线程池
Q: ThreadLocal的常见使用场景?A:每个线程中需要维护1个不同的副本, 但这个副本可能是某一个时刻一起塞入每个线程的, 只不过之后该副本的变化 不再受其他线程的影响。常见场景有连接器管理模块connectorManager, 每个线程持有的connect变量是单独使用的,不会互相影响或者需要加锁。原因就是将其作为副本放入每个线程,当线程启动连接或者关闭时,不影响其他线程里的getConnect方法
Q: ThreadLocal和Synchronized关键字的区别?A:Synchronized是用时间的消耗,来换取数据同步以及互不冲突ThreadLocal则是用空间的消耗,来换取数据之间互不冲突(不涉及同步)
Q:TheadLocal在每个线程中是以什么形式存储的? 原理是什么A:在某个线程中调用 某threadlocal.set(value)时, 其实就是在该线程中新建了1个threalocalMap, 然后把threadLocal作为键,value作为值,放进本线程的threalocalMap中。当在线程中调用threadlocal.get()的时候,就是从线程的threadLocalMap中获取这个threadLocal对应的值. 如果get不到,则可以通过自定义initValue方法生成一个threadLocal的默认值
ThreadLocal
Java多线程基础Q&A
0 条评论
回复 删除
下一页