您好,欢迎光临本网站![请登录][注册会员]  
文件名称: 多线程面试题
  所属分类: Java
  开发工具:
  文件大小: 2mb
  下载次数: 0
  上传时间: 2019-10-12
  提 供 者: weixin_********
 详细说明:详细讲解的多线程中遇到或者存在的问题,对各类多线程问题进行分析解读,为求职者提供了良好的资源ConcutrentHash Map 采用分段锁技术、同步容器中,是一个容晷一个嶺,但在 Concurrenthushm中,会将hush麦的数组部分分成干段,每段维 护一个钡,以达到高效的并发访 13.什么是多线程的上下文切换? 1、多线程:是从软件或者硬件上实现多个线程的并发技术。 2、多线程的好处 便用多线程可以把程序中占据时间长的任务放到后台去处理,如图片、视屏的下载 ⅱ.发挥多核处珪器的优势,并发执行让系统运行的更快、更流畅,用户体验更好 、多线程的缺点 1.大量的线程降低代码的可读性; 2.更多的线程需要更多的内存空间 3.当多个线程对同一个资源出现争夺时侯要注意线程安全的问题。 4、多线程的上下文切换 cP通过时间片分配算法来循环执行任务当前任务热行一个时间片后会切换到下一个任务。但是在切换前会保 存上一个任务的状态,以便下次切换回这个任务时,可以再次加载这个任务的状态 14. Threadlocal的设计理念与作用? 1、Java中的 Threadloca类允许我们创建只能被同一个线程读写的变量。囚此,如果一段代码含有一个 Threadlocal变量 的引用,即使两个线程同时执行这段代码,它们也无法访问到对方的 Threadlocal变量。 1、概念:绒程局部变量。在拌发编程的时候,成员变量如果不做任何处理其实是线程不安全旳,各个线程都在操作同一个变量,显 然是不行的,并且我们也知道 volati1e这个关键字也是不能保证线程安全的。那么在有一种情况之下,我们需要满足这样一个条件:变 量是同一个,但是每个线程都使用同一个初始值,也就是偯用同一个变量的一个新的副本。这种情况之下 Thread,oca1就非常适用:比 如说λ∩的数据库连接,我们知道A○是单例的,那么他的属性 Connect icn就不是一个线程安全的变量。而我们每个线程都需要使用 他,并目各自使用各自的。这种情况, Thredclocd就比较好的解决了这个问题。 2、原琿:从本质来讲,就是每个线程都维护了一个m=p,而这个dp的key就是 irecdlocc l,而值就是我们seL的那个值,每次 线程在get的时候,都从自己的变量中取值,既然从自己的变量中取值,那肯定就不存在线程安全问题,总体來讲, Threadlocal这个 变量的状态根本没有发生变化,他仅仅是充当一个写时使用,适合做缓存,在程序启动时初始化,之后可以被多个线程访问; 3、hash冲突 1、简介: HashMal中调用 hash Code)方法来计算 hashCode。由于在Java中两个不同的对象可能有一样的 hashcode,所以不同的键可能有一样 hash code,从而导致冲突的产生。 2、hash冲突解决:使用平衡树来代替链表,当同-hash中的元素数量超过特定的值便会由链表切换到平衡树 4、无锁读: ConcurrenthashMap之所以有较好的并发性是因为 ConcurrentHashMap是无锁读和加锁写,并且利用了分 段锁(不是在所有的 entry上加锁,而是在一部分 entry上加锁) / Specialized implementations of map methods 4/ v get(object key, int hash)t if (count != 0)[// read-volatile HashEntrye= getFirst(hash); while (e != null)i if (e. hash =s hash & key equals(e. key ))t VV=e value if (v!= null) return v; return readvalueUnderLock(e)i // recheck next return nul 读之前会先判断 count(idk16),其中的coun是被 volatile修饰的(当变量被 volatile修饰后,每次更改该变量的时候会将更 改结果写到系统主內存中,利用多处理器的缓存一致性,其他处理器会发现自己的缓存行对应的内存地址被修改,就会将自己处 理器的缓存行设置为失效,并强制从系统主内存获取最新的数据。),故可以实现无锁读。 5、 ConcurrentHash Map的并发度就是 segment的大小,默认为16,这意味着最多同时可以有16条绒程操作 ConcurrentHashMap,这也是 ConcurrentHash Map对 Hashtable的最大优势 22. Reentrant Read writelock读写锁的使用? 1、读写锁:分为读锁和写锁,多个读锁不互压_读钞与写锁互压,这是由jvm自己控制的,你只要上好相应的锁即可 2、如果你的代码只读数据,可以很多亼同时读,但不能同时写,那就上读锁 3、如果你的代码修改薮据,只能有一◇人在写,且不能同时读取,那就上写锁。总之,读的时候上读锁,写的时候上写 锁! 23, Cyclic Barrier和 CountDownLatch的用法及区别? CyclicBarrier和 CountDownLatch都位于 Java util. concurrent这个包下 Count DownLatch CyclicBarricr 减计数方式 加计数方式 计算为0时释放所有等待的线程 计数达到指定值时释放所有等待线程 计数为0时,无法重置 计数达到指定值时,计数置为0重新开始 调用 count Down(方法计数减一,调用awe法只走行阻塞,调用aa法计数加1,若加1后的值不等于 对计数没任何影响 构造方法的值,则线程阻塞 不可重复利用 可重复利用 24. eeksurpper王具? LockSupport是JDK中比较底层的类,用来创建锁和其他同步工具类的基本线程阻塞。java锁和同步器框架的核心AQS AbstractQueued Synchronizer,就是通过调用 Lock support park(和 LockSupport. park()实现线程的阻塞和唤醒的 25. Condition接口及其实现原理? 1.在 java util. concurrent包中,有两个很特殊的工具类, Condition和 Reentrant lock,使用过的人都知道 Reentrantlock(重入锁)是jdk的 concurrent包提供的一种独占锁的实现 2.我们知道在线程的同步时可以使一个线程阻塞而等待一个信号,同时放弃锁使其他线程可以能竞争到锁 3.在 synchronized中我们可以使用 Object的wait和notf方法实现这种等待和唤醒 4.但是在Lock中怎么实现这种wat和not呢?答案是 Condition,学习 Condition主要是为了方便以后学习 blockqueue和 concurrenthashmap的源码,同时也进一步理解 Reentrantlock。 26.Fork/Join框架的理解? 1、Fok就是把一个大任务切分为着干子任务并行的热行。 2、Join就是合并这些子任务的执行结果,最后得到这个大任务的结果。 27.wait()和seep)的区别? 方法是线程类( Thread)的静态方法,让调用线程进入睡旺状态,让出执行机会给其他线程,等到休眠时间结束 后,线程进入就绪状态和其他线程一起竞争cpu的执行时间 因为sep)是 static静态的方法,他不能改变对象的机锁,当一^ synchronized块中调用了 sleep)方法,线程虽然 进入烋眠,_但是对象的机锁没有被释放,其他线稈依然无法访问这个对象 2、wait wait()是 object类的方法,当一个线程执行到wait方法时,它就进入到一个和该对象相关的等待池,同时释放对象的 机锁,使得其他线程能够访问,可以通过 notify, notify方法来唤醒等待的线程 28.线程的五个状态(五种状态,创建、就绪、运行、阻塞和死亡)? 被其他线程唤醒 tf0或者 锁池 Q 等待队列 lock pool release lock会释放锁 or monitor 刭锁标识 synchronized (o) owaito 获取时间片 新建 t, atart o optain y timcsli Thread t new 可运行状态 运行状态2异常出万法 死亡 running ⊥、时问片用完 2、 Thread, yield 1、用户输入完成 1、务待用户输入 2、seO时问结束 2、/ Thread.seep 3、t2线程结束 阻塞状态 t2. join( ny monitor 会释放锁 其做建状 新建(New se时或完成 sep或on或10请求 就绪( Runnable 运行(Rm)mm行完毕元亡(d) 调度器〕 得对象的锁 synchronized 阻寒在对象的锁池中 阻塞在对象的等待池中 Blocked in objects 〔 Blocked in Object's wait lock pool) pool) 线程道常都有五种状态,创建、就绪、运行、阻塞和死亡。 .第一是创建状态。在生成线程对象,并没有调用该对象的sta方法,这是线程处于创建状态 ⅱ.第二是就绪状态。当调用了线稈对象的star方汯之后,该线程就进入了就绪状态,但是岀时线程调度程序还没有 把该线程设置为当前线程,此时处于就绪状态。在线程运行之后,从等待或者睡眠中回来之后,也会处于就绪状 态 ⅲ第三是运行状态。线程调度稈序将处于就绪状态的线程设置为当前线程,此时线程就讲入了运行状态,开始运行 run函数当中的代码。 ⅳ.第四是阻塞状态。线程正在运行的时候,被暂停:通常是为了等待某个时间的发生(比如说某项资源就绪)之后再 继续运行。secp, suspend,wait等方法都可以导致线程阻塞。 v.第五是死亡状态。如果一个线程的ru方法执行结束或者调用stop方法后,该线程就会死亡。对于已经死亡的线 程,无法再使用star方法令其进入就绪。 29. start0方法和run(方法的区别? tart方法来启动一个线程,真正实现了多线程运行 2、如果直接调用run,其实就相当于是调用了一个普通函数而已,直接调用run方法必须等待run方法执行完毕才能热 行下面的代码所以热行路径还是只有一条,根本就没有线程的特征,所以在多线程执行时要使用 start方法而不是run方法。 30, Runnable接口和 callable接口的区别? 1. Runnable接口中的run(方法的返回值是woid,它做的事情只是纯粹地去执行run0)方法中的代码而已 2. Callable接口中的ca方法是有返回值的,是一个泛型,和 Future、 Futuretask配合可以用来获取异步执行的结果 31. volatile关键字的作用? 1.多线程主要围绕可见性和原子性两个特性而展开,使用 volatile关键字修饰的变量,保证了其在多线程之间的可见性 即每次读取到 volatile变量,一定是最新的数据 2.代码底层执行不像我们看到的高级语言—Java程序这么简单,它的执行是Java代码>字节码->根据字节码执行对应 勺CC-+代码->CC++代码被编译成汇编语言→>和硬件电路交互,现实中,为了取更奷旳性熊JM可能会对指佥讲行 重排序,多线程下可能会岀现一些意想不到的问题。使目 volatile则会对禁止语义重排序,当然这也一定程度上隆低了代 码执行效率。 32.Java中如何获取到线程dump文件? 死循环、死锁、阻謇、仄面打开慢等问題,查看线程dump是最好的解决问题的途径。所谓线程σum也就是线程堆栈, 获取到线程堆栈有两步: 获取到线程的pd,可以通过使用jps命令,在Linx环境下还可以使用ps- ef _grep java 2、打印线程堆栈,可以通过使用 stack pid命貪,在 Linux环境下还可以使用ki-3pi 3、另外提一点, Thread类提供了一个 getstackTrace(方法也可以用于获取线程堆栈。这是一个实例方法,因此此方法 是和具体绒程实例绑定的,每次荻服刳的是具体棊个线程当節运行的堆栈 33.线程和进程有什么区别? 1.进程是系统讲行资源分配的基本单位,有独立的内存地址罕间 2.线程是CP独立运行和独立调度的基本单位,没有单独地址空间,有独立的栈,局部变量,宥存器,程序计数器等。 3.创建进程的开销大,包括创建虚拟地址空间等需要大量系统资源 4.创建线程开销小,基本上只有一个内核对象和一个堆栈 5.一^进程无法直接访问另一个进程的资源;同一进程内的多个线程共烹进程的资源。 6.进程切换开销大,线程切换开销小;走程间通信开销大,线程间通信开销小。 7.线程属于进程,不能独立执行。每个进程至少要有一个线程,成为主线程 34.线程实现的方式有几种(四种)? 1.继承 Thread类,重写run方法 2.实现 Runnable接口,亘写run方法,实现 Runnable接口的实现类的实例对象作为 Thread构造函数的 target 3.实现 Callable接口通过 FutureTask包装器来创建 Thread线程 4.通过线程池创建线程 1 public class ThreadDemo03 t public static void main(Stringl args)i Callable oneCal Lable= new Ti cketso: FutureTaskcObject> one Task= new Future Task(one Callable) Thread t= new Thread(one Task System. out. println(Thread. currentThreado. getName O) 10 11 cLass Tickets imp Lements Callable I //重写ca1l方法 Override public Object callo throws Exception t TODO Auto-generated method stub System.out. println( Thread. currentThread(. getName)+"->我是通过实现 Callable接口通过Fut return nuLl 35,高并发、任务执行时间短的业务怎样使用线程池?并发不高、任务执行时间长的业务怎样使用线程池?并发高、 业务执行时间长的业务怎样使用线程池? 1.高并发、任务执行时间短的业务:线程池线程数可以设置为cPU核数+1,减少线程上下文的切换。 2.并发不高、任务执行时间长的业务要区分开看 a.假如是业务时间长集中在O操作上,也就是|O密集型的任务,因为O操作井不占用cp∪,所以不要让所有的CpU 困下来,可以加大线池中的线程数目,让CPU处理更多的ψ务 b假如是业务时间长集中在计算操作上,也就是计算密集型任务,这个就没办法了,和(1一样吧,线程池中的线 程数没置得少一些,淢少线程上下文的切換 3.并发高、业务抗行时间长,解决这种类型任务旳关键不在于线程池而在于整体架构的设计,看看这些业务里面某些数 据是否能做缰存是第一步、增加服务器是第二步,至于线程池的设置,设置参考(2)。最后,业务执行时间长的问题, 也可能需要分析一下,看看能不能使用中间件对任务进行拆分和解耦。 36.如果你提交任务时,线程池队列已满,这时会发生什么? 1、如果你使用的 Linked BlockingQueue;也就是无界队列的话,没关系;续添加任务到阳塞队列中等待执行,因为 Linked BlockingQueue可以近乎认为是一个无穷大的队列,可以无限存放任务 2、如果你使用的是有界队列比方说 Array Blocking Queue的话,任务首先会被添加到 Array BlockingQueue中, Array Blocking Queue满了,则会使用拒绝策略 Rejected ExecutionHandler处理满了的任务,默认是 AbortPo 37,锁的等级:方法锁、对象锁、类锁? 1.方法锁( synchronized修饰方法时) a通过在方法声明中加入 synchronized关键字来声明 synchronized方法。 b. synchronized方法控制对类成员变量的访问 C.每个类买例对应一捫锁,每个 synchronized方法都必须获得调用该方法的类实例的锁方能执行,否则所属线程阻 塞,方法一旦执行,就独占该锁,直到从该方法返回时才将锁释放,此后被阻塞的线程方能获得该锁,重新进入可 执行状态。这种机制确保了同一时刻对于每一个类实何,其所有声明为 synchronized的成员函数中至多只有一个处 于可执行状态,从而有效避免了类成员变量的访问冲突 2.对象锁( synchronized修饰方法或代码块) a.当一个对象中有 synchronized mcthod或 synchronized block的时候调用此对象的同步方法或进入其同步区域时, 就必须先获得对象锁。如果比对象的对象锁已被其他调用者占用,则需要等待此锁被释放。(方法锁也是对象锁 b java的所有对象都含有1个互斥锁,这个锁由JvM自动获取和释放。线程进入 synchronized方法的时候获取该对象 的锁,当然如果已经有线程获取了这个对象的锁,那么当前线程会等待; synchronized方法正常返回或者抛异常面 终止、JVM会自动释放对象锁。这里也体现了用 synchronized来加锁的1个好处,方法抛异常的时候,锁仍然可以由 JVM来自动释放。 3.类锁( synchronized修饰静态的方法或代码块) a.由于一个cass不论被实例化多少次,其中的静态方法和静态变量在内存中都只有一份。所以,一旦一个静态的方 法被申明为 synchronized,此类所有的实例化对象在调用此方法,共用同一把锁,我们称之为类 4.对象锁是用来控制实例方法之间的同步,类锁是用来控制静态方法(或静态变量互斥徠)之间的同步 38.如果同步块内的线程抛出异常会发生什么? synchronized方法正常返回或者抛异常而终止,JVM会自动释放对象钡 39并发缩程( concurrency)并行编程( parallellism)有什么区别? 1.解释一:并行是指两个或者多个事件在同一时刻发牛;而并发是指两个或多个軎件在同一时间间隔发牛。 2.解释二:并行是在不同实体上的多个事件,并发是在同一实体上的多个事件。 3.解释三:在一台处理器上“同时”处理多个任务,在多台处理器上同时处理多个任务。如 hadoop分布式集群 所以并发编程的目标是充分的利用处理器的每一个核,以达到最高的处理性能。 40.如何保证多线程下i++结果正确? 1. volatile只能保证你数据的可见性,获取到的是最新的数据,不能保证原子性; 2用 AtomicInteger保证原子性。 3. synchronized既能保证共享变量可见性,也可以保证锁內操作的原子性 41.一个线程如果出现了运行时异常会怎么样? 1.如耒这个异常没有被捕获的话,这个线程就停止执行了。 2.另外重要的一点是:如果这个线程持有某个对象的监视器,那么这个对象监视器会被立即释放 42.如何在两个线程之间共享数据? 通过左线程之问共亨对象就可以了,然后通过wat/ otify/notify、awat/sign叫 a/signalA进行唤起和等待,比方说阻塞 队列 Blocking Queue就是为线程之间共享数据而设计的。 卖票系统 1 package多线程共享数据 public class Ticket imp lements Runnable private int ticket= 10; public void runo t hile(tickets)L System.out. println("当前票数为:"+ ticket) 12 package多线程共享数据; 13 public class SellTicket t public static void main(String args) t Ticket t= new Ticket; new Thread(t). start new Thread(t). start 银行存取款 public class MyData t private public synchronized void addot System.out. printLn("线程"+ Thread ntThreadO. getName(+ j33:+3) public synchronized void decot System. out. printLn(## +Thread. current Thread. getName(+13:+]) public int getDataot 16 public class AddRunnable implements Runnable pubLic AddRunnable(MyData data)t this data= data; 20 blic void runo t data. addo 26 public class DecRunnable implements Runnable i MyData data; pubLic DecRunnable(MyData data)t this data data public void runo i data. deco); 36 public class TestOne t public static void main(string args ) i MyData data= new MyDatao Runnable add= new AddRunnable(data) Runnable dec new DecRunnable(data) for (int 1=0; 1<2; i++)i new Thread(add). start new Thread(dec), start; 43.生产者消费者模型的作用是什么? 1.通过平衡生产者的生产能力和逍费者的消费能力来提升整个系统的运冮效率,这是生产者消费者模型最重要的作用。 2.解耦,这是生产者消费者模型附带的作用,解耦意味看牛产者和消费者之间的联系少,联系越少越可以独自发展而不 需要受到相互的制约 44.怎么唤醒一个阻塞的线程? 1.如线程是因为调用了wait)slep)者join)方法而导致的阻寒
(系统自动生成,下载前可以参看下载内容)

下载文件列表

相关说明

  • 本站资源为会员上传分享交流与学习,如有侵犯您的权益,请联系我们删除.
  • 本站是交换下载平台,提供交流渠道,下载内容来自于网络,除下载问题外,其它问题请自行百度
  • 本站已设置防盗链,请勿用迅雷、QQ旋风等多线程下载软件下载资源,下载后用WinRAR最新版进行解压.
  • 如果您发现内容无法下载,请稍后再次尝试;或者到消费记录里找到下载记录反馈给我们.
  • 下载后发现下载的内容跟说明不相乎,请到消费记录里找到下载记录反馈给我们,经确认后退回积分.
  • 如下载前有疑问,可以通过点击"提供者"的名字,查看对方的联系方式,联系对方咨询.
 相关搜索: 多线程面试题
 输入关键字,在本站1000多万海量源码库中尽情搜索: