多线程面试题

什么是多线程?

多线程(英语:multithreading),是指从软件或者硬件上实现多个线程并发执行的技术。具有多线程能力的计算机因有硬件支持而能够在同一时间执行多于一个线程,进而提升整体处理性能。具有这种能力的系统包括对称多处理机、多核心处理器以及芯片级多处理(Chip-level multithreading)或同时多线程(Simultaneous multithreading)处理器。在一个程序中,这些独立运行的程序片段叫作“线程”(Thread),利用它编程的概念就叫作“多线程处理(Multithreading)”。具有多线程能力的计算机因有硬件支持而能够在同一时间执行多于一个线程,进而提升整体处理性能。

线程和进程有什么区别?

进程是指一种“自包容”的运行程序,有自己的地址空间;线程是进程内部单一的一个顺序控制流 进程:每个进程都有独立的代码和数据空间(进程上下文),进程间的切换会有较大的开销,一个进程包含1--n个线程。(进程是资源分配的最小单位) 线程:同一类线程共享代码和数据空间,每个线程有独立的运行栈和程序计数器(PC),线程切换开销小。(线程是cpu调度的最小单位 线程和进程一样分为五个阶段:创建、就绪、运行、阻塞、终止。 线程的运行中需要使用计算机的内存资源和CPU。

如何在Java中使用新线程?

java开启新线程有三种方法:

方法1:继承Thread类;

方法2:实现Runnable接口;

方法3:直接在函数体使用(匿名内部类);

start()和run()有什么区别?

start:用start方法来启动线程,真正实现了多线程运行,这时无需等待run方法体代码执行完毕而直接继续执行下面的代码。通过调用Thread类的start()方法来启动一个线程,这时此线程处于就绪(可运行)状态,并没有运行,一旦得到cpu时间片,就开始执行run()方法,这里方法 run()称为线程体,它包含了要执行的这个线程的内容,Run方法运行结束,此线程随即终止。
run:run()方法只是类的一个普通方法而已,如果直接调用Run方法,程序中依然只有主线程这一个线程,其程序执行路径还是只有一条,还是要顺序执行,还是要等待run方法体执行完毕后才可继续执行下面的代码,这样就没有达到写线程的目的。总结:调用start方法方可启动线程,而run方法只是thread的一个普通方法调用,还是在主线程里执行。这两个方法应该都比较熟悉,把需要并行处理的代码放在run()方法中,start()方法启动线程将自动调用 run()方法,这是由jvm的内存机制规定的。并且run()方法必须是public访问权限,返回值类型为void.。

总结:调用start方法方可启动线程并允许run()方法,而run方法只是thread的一个普通方法调用,还是在主线程里执行。

Thread.join方法有什么用?

简单来说就是,你在家看电视,突然有人敲门叫你交水电费,你必须先交完费用才能继续看电视。也就是说,你必须等待那个插入的线程完成才能继续。

假如新建T1,T2,T3三个线程,如何保证它们按顺序执行?

可以在他们开启state()之后join(),也可以使用锁lock()或者synchronized

volatile变了是做什么的?

a.volatile关键字为域变量的访问提供了一种免锁机制;
b.使用volatile修饰域相当于告诉虚拟机该域可能会被其他线程更新;
c.因此每次使用该域就要重新计算,而不是使用寄存器中的值;
d.volatile不会提供任何原子操作,它也不能用来修饰final类型的变量;

如果一个线程中发生了异常会怎么样?

① 如果该异常被捕获或抛出,则程序继续运行。 
② 如果异常没有被捕获该线程将会停止执行。 
Thread.UncaughtExceptionHandler是用于处理未捕获异常造成线程突然中断情况的一个内嵌接口。当一个未捕获异常将造成线程中断的时候JVM会使用Thread.getUncaughtExceptionHandler()来查询线程的UncaughtExceptionHandler,并将线程和异常作为参数传递给handler的uncaughtException()方法进行处理。

什么是ThreadLocal变量?

ThreadLocal用于保存某个线程共享变量:对于同一个static ThreadLocal,不同线程只能从中get,set,remove自己的变量,而不会影响其他线程的变量。
1、ThreadLocal.get: 获取ThreadLocal中当前线程共享变量的值。
2、ThreadLocal.set: 设置ThreadLocal中当前线程共享变量的值。
3、ThreadLocal.remove: 移除ThreadLocal中当前线程共享变量的值。
4、ThreadLocal.initialValue: ThreadLocal没有被当前线程赋值时或当前线程刚调用remove方法后调用get方法,返回此方法值。

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

将线程添加到一个队列中,下次创建时查询池中是否存在,线程数量不能超过最大数。超过最大值的线程可以排队,但他们要等到其他线程完成后才启动。
优点:
1.创建/销毁线程伴随着系统开销,过于频繁的创建/销毁线程,会很大程度上影响处理效率,减少资源消耗。
2.线程并发数量过多,抢占系统资源从而导致阻塞,处理线程安全问题。
3.对线程进行一些简单的管理,如:延时执行、定时循环执行的策略。

Thread.sleep 和 wait 方法有什么不同?

sleep 是线程类(Thread)的方法,导致此线程暂停执行指定时间,给执行机会给其他线程,但是监控状态依然保持,到时后会自动恢复,调用sleep 不会释放对象锁。由于没有释放对象锁,所以不能调用里面的同步方法。
sleep()使当前线程进入停滞状态(阻塞当前线程),让出CUP的使用、目的是不让当前线程独自霸占该进程所获的CPU资源,以留一定时间给其他线程执行的机会;
sleep()是Thread类的Static(静态)的方法;因此他不能改变对象的机锁,所以当在一个Synchronized块中调用Sleep()方法是,线程虽然休眠了,但是对象的机锁并木有被释放,其他线程无法访问这个对象(即使睡着也持有对象锁)。

在sleep()休眠时间期满后,该线程不一定会立即执行,这是因为其它线程可能正在运行而且没有被调度为放弃执行,除非此线程具有更高的优先级。
wait()方法是Object类里的方法;当一个线程执行到wait()方法时,它就进入到一个和该对象相关的等待池中,同时失去(释放)了对象的机锁(暂时失去机锁,wait(long timeout)超时时间到后还需要返还对象锁);可以调用里面的同步方法,其他线程可以访问;
wait()使用notify或者notifyAlll或者指定睡眠时间来唤醒当前等待池中的线程。
wiat()必须放在synchronized block中,否则会在program runtime时扔出”java.lang.IllegalMonitorStateException“异常。
总结:sleep与wait不同之处:sleep来自Thread,wait来自Object,sleep不会释放对象锁,wait会释放对象锁,sleep不用再synchronized中,wait必须要在synchronized中否则会抛出异常。

synchronized 关键词是做什么的?

预防线程安全问题,同一时间只能有一个线程访问标有synchronized关键字的方法,变量,类。

原文地址:https://www.cnblogs.com/Qi1007/p/9472565.html