多线程面试题汇总(深入理解)

线程状态切换图

 

什么是线程?

线程是操作系统能够进行运算调度的最小单位,它被包含在进程之中,是进程中的实际运作单位。不同进程使用不同的内存空间,而所有的线程共享一片相同的内存空间。别把它和栈内存搞混,每个线程都拥有单独的栈内存用来存储本地数据。如果一个线程完成一个任务要100毫秒,那么用十个线程完成该任务只需10毫秒。

如何在Java中实现线程,区别是什么?

  • 继承Thread类,缺点是java中的类仅支持单继承,只能扩展一个外部类,线程之间没有联系;
  • 实现Runnable接口类,重写run()方法实现线程,可以处理同一资源,实现资源共享;
  • 实现Callable接口类,重写call()方法实现线程,有返回值和抛出异常,可以返回装载有计算结果的Future对象。

Thread类中start()run()方法有什么区别?

start()方法被用来启动新创建的线程,其内部调用了run()方法。run()称为线程体,通过调用Thread类的start()方法来启动一个线程。

Java中的volatile关键字是什么?和atomic有什么区别?

可见性(即一个线程修改了某个变量的值,这个值对其他线程是立即可见的)。

禁止进行指令重排序(指令重排序:处理器为了提高程序运行效率,可能会对输入代码进行优化,它不保证程序中各个语句的执行先后顺序同代码中的顺序一致,但是它会保证程序最终执行结果和代码顺序执行的结果是一致的)。

缺点:不支持原子性。而atomic具有原子性。

Java堆和栈有什么不同?

每个线程都有自己的栈内存,用于存储本地变量、方法参数和栈调用,一个线程中存储的变量对其它线程是不可见的。而堆是所有线程共享的一片公用内存区域。对象都在堆里创建,为了提升效率线程会从堆中弄一个缓存到自己的栈,如果多个线程使用该变量就可能引发问题,这时volatile变量就可以发挥作用了,它要求线程从主存中读取变量的值。

如何避免死锁?

避免死锁最简单的方法就是将系统中所有的资源设置标志位、排序,规定所有的进程申请资源必须以一定的顺序(升序或降序)做操作来避免死锁。

什么是线程池?为什么要使用它?

如果任务来了才创建线程,那么响应时间会变长,并且一个进程能创建的线程数有限。为了避免这些问题,在程序启动时就创建若干线程来响应处理,它们被称为线程池,里面的线程叫工作线程。

怎么检测一个线程是否拥有锁?

在java.lang.Thread中有一个方法叫holdsLock(),它返回true就是拥有锁。

Java中活锁和死锁有什么区别?

活锁的进程状态可以改变但是却不能继续执行。比如两个人在狭小的走廊碰到,两个人都试着避让对方好让彼此通过,但是因为避让的方向都一样导致最后谁都不能通过走廊。

javawaitsleep方法的不同?

在等待时wait会释放锁,而sleep一直持有锁。wait通常被用于线程间交互,sleep通常被用于暂停执行。

如果你提交任务时,线程池队列已满。会时发会生什么?

ThreadPoolExecutor的submit()方法将会抛出一个RejectedExecutionException异常。

什么是线程安全?

多个线程同时运行一个代码,如果每次运行结果和单线程运行的结果一样,就是线程安全的。

JavanotifynotifyAll有什么区别?

只有一个线程在等待状态时notify()才有用武之地。notifyAll()唤醒所有线程并允许他们争夺锁,确保了至少有一个线程能继续运行。

为什么waitnotifynotifyAll这些方法不在thread类里面?

每个对象都有锁,通过线程获得。由于wait、notify、notifyAll都是锁级别的操作,所以把他们定义在Object类中因为锁属于对象。

什么是ThreadLocal变量?

ThreadLocal解决多线程中因并发产生数据不一致问题。ThreadLocal为每个线程中并发访问的数据提供一个副本,通过访问副本来运行业务,这样的结果是耗费了内存,但大大减少了线程同步所带来性能消耗,也减少了线程并发控制的复杂度。

ThreadLocal和Synchonized都用于解决多线程并发访问。但是他们有本质区别。synchronized是利用锁的机制,使变量或代码块在某一时该只能被一个线程访问。而ThreadLocal为每一个线程都提供了变量的副本,使得每个线程在某一时间访问到的并不是同一个对象,这样就隔离了多个线程数据共享。而Synchronized却正好相反,它用于在多个线程间通信时能够获得数据共享。

Javasynchronized ReentrantLock 有什么不同?

synchronized有一些缺点。比如你不能扩展锁之外的方法或者块边界,尝试获取锁时不能中途取消等。ReentrantLock类拥有与synchronized相同的并发性和内存语义且它还具有可扩展性。

Java中的ReadWriteLock是什么?

读写锁分为读锁和写锁,上读锁时允许多个用户进行读操作,上写锁时,只允许一个用户进行写操作。读写锁最适用于对数据结构的读操作次数多于写操作的场合。

什么是阻塞式方法?

阻塞式方法是指程序会一直等待该方法完成期间不做其他事情。

有三个线程T1T2T3,怎么确保它们按顺序执行?

在多线程中有多种方法让线程按特定顺序执行,你可以用线程类的join()方法在一个线程中启动另一个线程,另外一个线程完成该线程继续执行。为了确保三个线程的顺序你应该先启动最后一个(T3调用T2,T2调用T1),这样T1就会先完成而T3最后完成。

 

发布了34 篇原创文章 · 获赞 36 · 访问量 4003

猜你喜欢

转载自blog.csdn.net/xieweikun_7/article/details/105281109