线程、多线程和线程池面试专题
android 多线程面试题

android 多线程面试题Android多线程面试题Android多线程是一个重要的技术,对于开发者来说,掌握多线程编程是非常必要的。
在Android面试中,经常会出现与多线程相关的问题。
下面将介绍一些常见的Android多线程面试题,希望能够帮助你在面试中更好地回答问题。
1. 什么是多线程?多线程是指在一个进程中同时执行多个任务的技术。
在Android中,多线程可以实现在后台同时进行多个任务,以提升用户体验和应用性能。
2. 在Android中有哪些实现多线程的方式?在Android中,有以下几种实现多线程的方式:a. 使用Thread类:可以通过继承Thread类或者创建Thread匿名内部类的方式来创建线程对象,重写run()方法来定义线程执行的操作。
b. 使用Runnable接口:通过创建一个实现Runnable接口的类的实例,将其作为参数传递给Thread类的构造函数来创建线程。
c. 使用HandlerThread类:HandlerThread是继承自Thread的一个类,它内部封装了一个Looper和Handler,可以方便地实现线程间的通信。
d. 使用AsyncTask类:AsyncTask是一个封装了异步操作的类,它可以在后台执行耗时操作,并在主线程更新UI。
3. 什么是主线程和子线程?主线程是指应用程序的主要执行线程,也称为UI线程。
它负责处理用户交互、更新UI等操作。
子线程是在主线程之外创建的线程,用于执行一些耗时的操作,以保证主线程不会被阻塞。
4. 如何在子线程中更新UI?在Android中,UI更新必须在主线程中进行,但有时需要在子线程中执行一些耗时操作。
可以通过以下几种方式在子线程中更新UI:a. 使用Handler:可以在子线程中通过Handler发送消息给主线程,然后在主线程中通过Handler处理消息,更新UI。
b. 使用runOnUiThread()方法:可以在子线程中通过Activity的runOnUiThread()方法来直接更新UI。
多线程常见面试题及答案

多线程常见⾯试题及答案1、如何在Java中实现线程(4种)?1.继承Thread类,重写run⽅法(其实Thread类本⾝也实现了Runnable接⼝)2.实现Runnable接⼝,重写run⽅法3.实现Callable接⼝,重写call⽅法(有返回值)4.使⽤线程池(有返回值)2、在具体多线程编程实践中,如何选⽤Runnable还是Thread?Java中实现多线程有两种⽅法:继承Thread类、实现Runnable接⼝,在程序开发中只要是多线程,肯定永远以实现Runnable接⼝为主,因为实现Runnable接⼝相⽐继承Thread类有如下优势:1、可以避免由于Java的单继承特性⽽带来的局限;2、增强程序的健壮性,代码能够被多个线程共享,代码与数据是独⽴的;适合多个相同程序代码的线程区处理同⼀资源的情况。
3、Thread类中的start()和run()⽅法有什么区别?start()⽅法来启动线程,真正实现了多线程运⾏,这时⽆需等待run⽅法体代码执⾏完毕⽽直接继续执⾏下⾯的代码:通过调⽤Thread类的start()⽅法来启动⼀个线程,这时此线程是处于就绪状态,并没有运⾏。
然后通过此Thread类调⽤⽅法run()来完成其运⾏操作的,这⾥⽅法run()称为线程体,它包含了要执⾏的这个线程的内容,Run⽅法运⾏结束,此线程终⽌,⽽CPU再运⾏其它线程。
run()⽅法当作普通⽅法的⽅式调⽤,程序还是要顺序执⾏,还是要等待run⽅法体执⾏完毕后才可继续执⾏下⾯的代码:⽽如果直接⽤run⽅法,这只是调⽤⼀个⽅法⽽已,程序中依然只有主线程–这⼀个线程,其程序执⾏路径还是只有⼀条,这样就没有达到多线程的⽬的。
4、Java中Runnable和Callable有什么不同相同点:1. 两者都是接⼝;(废话)2. 两者都可⽤来编写多线程程序;3. 两者都需要调⽤Thread.start()启动线程;不同点:1. 两者最⼤的不同点是:实现Callable接⼝的任务线程能返回执⾏结果;⽽实现Runnable接⼝的任务线程不能返回结果;2. Callable接⼝的call()⽅法允许抛出异常;⽽Runnable接⼝的run()⽅法的异常只能在内部消化,不能继续上抛;注意点:Callable接⼝⽀持返回执⾏结果,此时需要调⽤FutureTask.get()⽅法实现,此⽅法会阻塞主线程直到获取‘将来’结果;当不调⽤此⽅法时,主线程不会阻塞!5、如何避免死锁?1. 加锁顺序按照顺序加锁是⼀种有效的死锁预防机制。
ios多线程面试题

ios多线程面试题在进行iOS多线程面试时,以下是一些常见的问题及其答案,帮助您更好地准备面试。
多线程是指同时执行多个线程的概念,它可以提高程序的运行效率。
在iOS开发中,多线程常用于处理耗时的操作,如网络请求、数据解析等,以避免阻塞主线程造成界面卡顿。
以下将介绍一些与iOS多线程相关的面试题目。
1. 什么是线程?线程是程序中的执行单元,是CPU调度和分派的基本单位。
每个进程至少有一个线程,称为主线程。
多线程是指同时运行多个线程。
2. iOS中常用的多线程技术有哪些?iOS中常用的多线程技术有以下几种:- Grand Central Dispatch (GCD)- NSOperationQueue- Thread3. Grand Central Dispatch (GCD)是什么?GCD是Apple推出的一套自动管理线程的技术,它使用了线程池的概念,通过将任务放入队列中,自动调度执行任务的线程。
GCD使用起来简单高效,是iOS开发中常用的多线程技术。
4. GCD中的队列有哪两种类型?GCD中的队列分为以下两种类型:- 串行队列:按照先进先出的顺序,依次执行队列中的任务。
- 并发队列:可以同时执行多个任务,任务之间的执行顺序不确定。
5. 什么是同步任务和异步任务?- 同步任务:在当前线程中执行,会阻塞当前线程,等待任务执行完毕后再继续执行后续代码。
- 异步任务:在新的线程中执行,不会阻塞当前线程,可以继续执行后续代码。
6. GCD中的dispatch_group有什么作用?dispatch_group用于在异步任务执行完毕后,执行特定代码。
dispatch_group_enter与dispatch_group_leave配合使用,用于标记任务的开始和结束,通过dispatch_group_notify方法执行指定代码。
7. NSOperationQueue与GCD有什么区别?- NSOperationQueue是基于GCD的更高级的多线程技术,支持添加依赖关系、取消操作等功能。
最全多线程经典面试题和答案

最全多线程经典⾯试题和答案Java实现线程有哪⼏种⽅式?1、继承Thread类实现多线程2、实现Runnable接⼝⽅式实现多线程3、使⽤ExecutorService、Callable、Future实现有返回结果的多线程多线程同步有哪⼏种⽅法?Synchronized关键字,Lock锁实现,分布式锁等。
Runnable和Thread⽤哪个好?Java不⽀持类的多重继承,但允许你实现多个接⼝。
所以如果你要继承其他类,也为了减少类之间的耦合性,Runnable会更好。
Java中notify和notifyAll有什么区别?notify()⽅法不能唤醒某个具体的线程,所以只有⼀个线程在等待的时候它才有⽤武之地。
⽽notifyAll()唤醒所有线程并允许他们争夺锁确保了⾄少有⼀个线程能继续运⾏。
为什么wait/notify/notifyAll这些⽅法不在thread类⾥⾯?这是个设计相关的问题,它考察的是⾯试者对现有系统和⼀些普遍存在但看起来不合理的事物的看法。
回答这些问题的时候,你要说明为什么把这些⽅法放在Object类⾥是有意义的,还有不把它放在Thread类⾥的原因。
⼀个很明显的原因是JAVA提供的锁是对象级的⽽不是线程级的,每个对象都有锁,通过线程获得。
如果线程需要等待某些锁那么调⽤对象中的wait()⽅法就有意义了。
如果wait()⽅法定义在Thread类中,线程正在等待的是哪个锁就不明显了。
简单的说,由于wait,notify和notifyAll都是锁级别的操作,所以把他们定义在Object类中因为锁属于对象。
为什么wait和notify⽅法要在同步块中调⽤?主要是因为Java API强制要求这样做,如果你不这么做,你的代码会抛出IllegalMonitorStateException异常。
还有⼀个原因是为了避免wait 和notify之间产⽣竞态条件。
什么是死锁?如何避免死锁?死锁就是两个线程相互等待对⽅释放对象锁。
程序员面试题精选100题

程序员面试题精选100题1. 什么是面向对象编程(OOP)?列举几种常见的面向对象编程语言。
2. 解释一下封装、继承和多态的概念。
3. 什么是数据结构?列举几种常见的数据结构。
4. 解释一下栈和队列的概念,并提供它们的实际应用场景。
5. 什么是算法?解释一下时间复杂度和空间复杂度的概念。
6. 解释一下HTTP协议的工作原理。
7. 什么是数据库事务?解释一下ACID原则。
8. 解释一下前端开发中的MVC和MVVM模式。
9. 解释一下正向代理和反向代理的区别。
10. 什么是RESTful API?列举一些常见的HTTP请求方法。
11. 解释一下同步和异步的概念,以及它们的区别。
12. 解释一下进程和线程的概念,并提供它们的区别。
13. 解释一下操作系统中的死锁问题,以及如何避免死锁。
14. 解释一下TCP/IP协议族的组成部分。
15. 什么是单元测试?解释一下TDD(测试驱动开发)的概念。
16. 解释一下版本控制系统中的分布式版本控制和集中式版本控制的区别。
17. 什么是软件设计模式?列举几种常见的软件设计模式。
18. 解释一下Web应用程序中的会话管理机制,以及如何处理会话跟踪。
19. 解释一下缓存的工作原理,并提供一些常见的缓存算法。
20. 什么是虚拟机?解释一下虚拟化技术的概念。
21. 解释一下操作系统中的文件系统,以及不同类型的文件系统。
22. 解释一下数据库索引的概念,以及为什么使用索引可以提高查询性能。
23. 什么是反射?解释一下反射在Java中的应用。
24. 解释一下关系型数据库和非关系型数据库的区别。
25. 什么是分布式系统?列举一些常见的分布式系统架构。
26. 解释一下HTTP和HTTPS的区别,以及为什么使用HTTPS更安全。
27. 解释一下云计算的概念,以及云计算的优势和劣势。
28. 什么是容器化?解释一下Docker的工作原理。
29. 解释一下RESTful风格的API设计原则。
15个顶级Java多线程面试题及答案

15 个顶级 Java 多线程面试题及答案1)此刻有 T1、T2、 T3 三个线程,你如何保证 T2 在 T1 履行完后履行, T3 在 T2 履行完后履行这个线程问题往常会在第一轮或电话面试阶段被问到,目的是检测你对”join ”方法能否熟悉。
这个多线程问题比较简单,能够用join 方法实现。
2)在 Java 中 Lock 接口比 synchronized 块的优势是什么你需要实现一个高效的缓存,它允很多个用户读,但只同意一个用户写,以此来保持它的完好性,你会如何去实现它lock 接口在多线程和并发编程中最大的优势是它们为读和写分别供给了锁,它能知足你写像ConcurrentHashMap 这样的高性能数据构造和有条件的堵塞。
Java 线程面试的问题愈来愈会依据面试者的回答来发问。
我激烈建议在你去参加多线程的面试以前仔细读一下Locks,因为目前其大批用于建立电子交易终统的客户端缓存和交易连结空间。
3)在 java 中 wait 和 sleep 方法的不一样往常会在电话面试中常常被问到的Java线程面试问题。
最大的不一样是在等候时wait 会开释锁,而 sleep 向来拥有锁。
Wait 往常被用于线程间交互,sleep 往常被用于暂停履行。
4)用 Java 实现堵塞行列。
这是一个相对困难的多线程面试问题,它能达到好多的目的。
第一,它能够检测侯选者能否能实质的用 Java 线程写程序;第二,能够检测侯选者对并发场景的理解,而且你能够依据这个问好多问题。
假如他用 wait() 和 notify() 方法来实现堵塞行列,你能够要求他用最新的Java 5中的并发类来再写一次。
5)用 Java 写代码来解决生产者——花费者问题。
与上边的问题很近似,但这个问题更经典,有些时候面试都会问下边的问题。
在Java中怎么解决生产者——花费者问题,自然有好多解决方法,我已经分享了一种用堵塞行列实现的方法。
有些时候他们甚至会问怎么实现哲学家进餐问题。
线程安全面试题

线程安全面试题在软件开发中,线程安全是一个重要的概念,特别是在多线程编程的场景下。
线程安全指的是多个线程同时访问共享资源时,不会产生不可预测的结果或者导致不一致的状态。
线程安全的实现必须考虑并发访问的问题,保证程序的正确性和可靠性。
本文将介绍几个与线程安全相关的常见面试题,并给出相应的答案和解析。
1. 什么是线程安全?线程安全是指多个线程同时访问一个共享资源时,不会导致数据的竞态条件(Race Condition)和其他的并发问题,确保程序的正确性和一致性。
2. 如何保证线程安全?实现线程安全的方法有多种,包括但不限于以下几种:- 使用互斥锁(Mutex)来确保同一时间只有一个线程可以访问共享资源。
- 使用信号量(Semaphore)来限制同时访问共享资源的线程数。
- 使用条件变量(Condition Variable)来实现线程之间的通信和协作。
- 使用原子操作(Atomic Operation)来保证特定操作的原子性。
- 使用线程安全的数据结构或者线程安全的库函数。
3. 什么是竞态条件?竞态条件是指多个线程同时访问共享资源时,由于执行的顺序不确定或者时间上的交错,导致程序的输出结果与执行的顺序不一致的情况。
竞态条件可能导致数据错乱、死锁、活锁等问题。
4. 怎样避免竞态条件?为了避免竞态条件,可以采取以下几种策略:- 使用互斥锁(Mutex)来确保同一时间只有一个线程可以访问共享资源。
- 尽量减少共享资源的使用,避免多个线程对同一资源的竞争。
- 使用原子操作(Atomic Operation)来保证特定操作的原子性,避免多个线程同时对同一数据进行读写。
- 合理设计线程间的通信和协作机制,避免死锁和活锁的发生。
5. 什么是死锁和活锁?死锁是指多个线程因为互相等待对方持有的资源而无法继续执行的状态,从而导致整个程序无法正常运行。
活锁是指多个线程在尝试解决冲突时,由于策略不当导致一直重复相同的操作而无法继续执行的状态。
线程池面试题的七个参数

线程池面试题的七个参数
线程池是并发编程中的重要概念,可以用于控制程序并发中线程的数量,以达到资源复用,降低开销的目的。
线程池的创建通常需要指定七个参数:
1. **核心线程数**:线程池中保持活动的最小线程数量。
新任务来临时,只有当线程池的当前数量小于核心线程数时,才会创建新的线程执行任务。
否则,任务会被放入到队列中等待。
2. **最大线程数**:线程池允许创建的最大线程数量。
如果队列满了,而且当前线程数量小于最大线程数,则创建新线程执行任务。
3. **存活时间**:非核心线程在队列中等待任务的最长时间。
如果在这段时间内,线程池没有接收到新任务,则会销毁空闲的线程。
4. **队列容量**:用于存储等待执行任务的队列的最大容量。
如果队列满了,那么新任务会阻塞直到有空间可用。
5. **拒绝策略**:当任务过多,而线程池的线程数量已达最大,且队列也已满时,如何处理新提交的任务。
常见的策略有抛出异常,丢弃当前任务,丢弃队列中最早的任务等。
6. **线程工厂**:用于创建新线程的工厂。
可以通过它自定义线程的外观,优先级等。
7. **任务调度器**:用于调度任务的调度器。
可以自定义任务的执行策略,如轮询,随机等。
以上就是创建线程池时通常需要考虑的七个参数。
根据实际应用场景的不同,参数的选择和设置也会有所不同。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
线程、多线程和线程池面试专题1、开启线程的三种方式?1)继承Thread类,重写run()方法,在run()方法体中编写要完成的任务new Thread().start();2)实现Runnable接口,实现run()方法new Thread(new MyRunnable()).start();3)实现Callable接口MyCallable类,实现call()方法,使用FutureTask类来包装Callable对象,使用FutureTask对象作为Thread对象的target创建并启动线程;调用FutureT ask对象的get()方法来获得子线程执行结束后的返回值。
FutureTask<Integer> ft = new FutureTask<Integer>(new MyCallable());new Thread(ft).start();2、run()和start()方法区别run()方法只是线程的主体方法,和普通方法一样,不会创建新的线程。
只有调用start()方法,才会启动一个新的线程,新线程才会调用run()方法,线程才会开始执行。
3、如何控制某个方法允许并发访问线程的个数?创建Semaphore变量,Semaphore semaphore = new Semaphore(5, true); 当方法进入时,请求一个信号,如果信号被用完则等待,方法运行完,释放一个信号,释放的信号新的线程就可以使用。
4、在Java中wait和seelp方法的不同wait()方法属于Object类,调用该方法时,线程会放弃对象锁,只有该对象调用notify()方法后本线程才进入对象锁定池准备获取对象锁进入运行状态。
sleep()方法属于Thread类,sleep()导致程序暂停执行指定的时间,让出CPU,但它的监控状态依然保存着,当指定时间到了又会回到运行状态,sleep()方法中线程不会释放对象锁。
5、谈谈wait/notify关键字的理解notify: 唤醒在此对象监视器上等待的单个线程notifyAll(): 通知所有等待该竞争资源的线程wait: 释放obj的锁,导致当前的线程等待,直接其他线程调用此对象的notify()或notifyAll()方法当要调用wait()或notify()/notifyAll()方法时,一定要对竞争资源进行加锁,一般放到synchronized(obj)代码中。
当调用obj.notify/notifyAll后,调用线程依旧持有obj锁,因此等待线程虽被唤醒,但仍无法获得obj锁,直到调用线程退出synchronized块,释放obj锁后,其他等待线程才有机会获得锁继续执行。
6、什么导致线程阻塞?(1)一般线程阻塞1)线程执行了Thread.sleep(int millsecond)方法,放弃CPU,睡眠一段时间,一段时间过后恢复执行;2)线程执行一段同步代码,但无法获得相关的同步锁,只能进入阻塞状态,等到获取到同步锁,才能恢复执行;3)线程执行了一个对象的wait()方法,直接进入阻塞态,等待其他线程执行notify()/notifyAll()操作;4)线程执行某些IO操作,因为等待相关资源而进入了阻塞态,如System.in,但没有收到键盘的输入,则进入阻塞态。
5)线程礼让,Thread.yield()方法,暂停当前正在执行的线程对象,把执行机会让给相同或更高优先级的线程,但并不会使线程进入阻塞态,线程仍处于可执行态,随时可能再次分得CPU时间。
线程自闭,join()方法,在当前线程调用另一个线程的join()方法,则当前线程进入阻塞态,直到另一个线程运行结束,当前线程再由阻塞转为就绪态。
6)线程执行suspend()使线程进入阻塞态,必须resume()方法被调用,才能使线程重新进入可执行状态。
7、线程如何关闭?1) 使用标志位2)使用stop()方法,但该方法就像关掉电脑电源一样,可能会发生预料不到的问题3)使用中断interrupt()public class Thread {// 中断当前线程public void interrupt();// 判断当前线程是否被中断public boolen isInterrupt();// 清除当前线程的中断状态,并返回之前的值public static boolen interrupted();}但调用interrupt()方法只是传递中断请求消息,并不代表要立马停止目标线程。
8、讲一下java中的同步的方法之所以需要同步,因为在多线程并发控制,当多个线程同时操作一个可共享的资源时,如果没有采取同步机制,将会导致数据不准确,因此需要加入同步锁,确保在该线程没有完成操作前被其他线程调用,从而保证该变量的唯一一性和准确性。
1)synchronized修饰同步代码块或方法由于java的每个对象都有一个内置锁,用此关键字修饰方法时,内置锁会保护整个方法。
在调用该方法前,需获得内置锁,否则就处于阴塞状态。
2)volatile修饰变量保证变量在线程间的可见性,每次线程要访问volatile修饰的变量时都从内存中读取,而不缓存中,这样每个线程访问到的变量都是一样的。
且使用内存屏障。
3)ReentrantLock重入锁,它常用的方法有ReentrantLock():创建一个ReentrantLock实例lock()获得锁unlock()释放锁4)使用局部变量ThreadLocal实现线程同步,每个线程都会保存一份该变量的副本,副本之间相互独立,这样每个线程都可以随意修改自己的副本,而不影响其他线程。
常用方法ThreadLocal()创建一个线程本地变量;get()返回此线程局部的当前线程副本变量;initialValue()返回此线程局部变量的当前线程的初始值;set(T value)将此线程变量的当前线程副本中的值设置为value5) 使用原子变量,如AtomicInteger,常用方法AtomicInteger(int value)创建个有给定初始值的AtomicInteger整数;addAndGet(int data)以原子方式将给定值与当前值相加6)使用阻塞队列实现线程同步LinkedBlockingQueue<E>9、如何保证线程安全?线程安全性体现在三方法:1)原子性:提供互斥访问,同一时刻只能有一个线和至数据进行操作。
JDK中提供了很多atomic类,如AtomicInteger\AtomicBoolean\AtomicLong,它们是通过CAS完成原子性。
JDK提供锁分为两种:synchronized依赖JVM实现锁,该关键字作用对象的作用范围内同一时刻只能有一个线程进行操作。
另一种是LOCK,是JDK提供的代码层面的锁,依赖CPU指令,代表性是ReentrantLock。
2)可见性:一个线程对主内存的修改及时被其他线程看到。
JVM提供了synchronized和volatile,volatile的可见性是通过内存屏障和禁止重排序实现的,volatile会在写操作时,在写操作后加一条store屏障指令,将本地内存中的共享变量值刷新到主内存;会在读操作时,在读操作前加一条load指令,从内存中读取共享变量。
3)有序性:指令没有被编译器重排序。
可通过volatile、synchronized、Lock保证有序性。
10、两个进程同时要求写或者读,能不能实现?如何防止进程的同步?我认为可以实现,比如两个进程都读取日历进程数据是没有问题,但同时写,应该会有冲突。
可以使用共享内存实现进程间数据共享。
11、线程间操作List12、Java中对象的生命周期1)创建阶段(Created):为对象分配存储空间,开始构造对象,从超类到子类对static成员初始化;超类成员变量按顺序初始化,递归调用超类的构造方法,子类成员变量按顺序初始化,子类构造方法调用。
2)应用阶段(In Use):对象至少被一个强引用持有着。
3)不可见阶段(Invisible):程序运行已超出对象作用域4)不可达阶段(Unreachable):该对象不再被强引用所持有5)收集阶段(Collected):假设该对象重写了finalize()方法且未执行过,会去执行该方法。
6)终结阶段(Finalized):对象运行完finalize()方法仍处于不可达状态,等待垃圾回收器对该对象空间进行回收。
7)对象空间重新分配阶段(De-allocated):垃圾回收器对该对象所占用的内存空间进行回收或再分配,该对象彻底消失。
13、static synchronized 方法的多线程访问和作用static synchronized控制的是类的所有实例访问,不管new了多少对象,只有一份,所以对该类的所有对象都加了锁。
限制多线程中该类的所有实例同时访问JVM中该类对应的代码。
14、同一个类里面两个synchronized方法,两个线程同时访问的问题如果synchronized修饰的是静态方法,锁的是当前类的class对象,进入同步代码前要获得当前类对象的锁;普通方法,锁的是当前实例对象,进入同步代码前要获得的是当前实例的锁;同步代码块,锁的是括号里面的对象,对给定的对象加锁,进入同步代码块库前要获得给定对象锁;如果两个线程访问同一个对象的synchronized方法,会出现竞争,如果是不同对象,则不会相互影响。
15、volatile的原理有volatile变量修饰的共享变量进行写操作的时候会多一条汇编代码,lock addl $0x0,lock前缀的指令在多核处理器下会将当前处理器缓存行的数据会写回到系统内存,这个写回内存的操作会引起在其他CPU里缓存了该内存地址的数据无效。
同时lock前缀也相当于一个内存屏障,对内存操作顺序进行了限制。
16、synchronized原理synchronized通过对象的对象头(markword)来实现锁机制,java每个对象都有对象头,都可以为synchronized实现提供基础,都可以作为锁对象,在字节码层面synchronized块是通过插入monitorenter monitorexit完成同步的。
持有monitor对象,通过进入、退出这个Monitor对象来实现锁机制。
17、谈谈NIO的理解NIO( New Input/ Output) 引入了一种基于通道和缓冲区的I/O 方式,它可以使用Native 函数库直接分配堆外内存,然后通过一个存储在Java 堆的DirectByteBuffer 对象作为这块内存的引用进行操作,避免了在Java 堆和Native 堆中来回复制数据。