b2科目四模拟试题多少题驾考考爆了怎么补救
b2科目四模拟试题多少题 驾考考爆了怎么补救

Java多线程面试问答(2019)(2)

电脑杂谈  发布时间:2020-05-29 02:22:13  来源:网络整理

这是上述问题的扩展. 活锁类似于死锁. 区别在于,活动锁中的线程或进程的状态不断变化. 活锁可以被视为一种特殊的饥饿感. 一个活锁的现实例子是两个人在一个小走廊里相遇. 他们都试图互相避开,以便彼此通过,但是由于避开的方向相同,所以没有人可以通过走廊. 简而言之,活锁和死锁之间的主要区别在于,前一个进程的状态可以更改,但不能继续执行.

在参加电话采访之前,我什至不知道我们甚至无法检测到线程是否拥有锁. 在java.lang.Thread中有一个名为holdLock()的方法,当且仅当当前线程拥有对特定对象的锁时,该方法才返回true.

对于不同的操作系统,有多种方法来获取Java进程的线程堆栈. 当您获得线程堆栈时,JVM会将所有线程的状态保存到日志文件或输出到控制台. 在Windows上,可以使用Ctrl + Break键组合来获取线程堆栈. 在Linux上,使用kill -3命令. 您也可以使用工具jstack来获取它. 它对线程ID进行操作. 您可以使用jps工具查找ID.

java线程死锁例子_java多线程避免死锁_避免线程死锁

问题很简单. -Xss参数用于控制线程的堆栈大小.

Java过去很长一段时间只能通过synced关键字实现互斥. 它有一些缺点. 例如,您不能扩展锁或块边界以外的方法,也不能在尝试获取锁时中途取消. Java 5通过Lock接口提供了更复杂的控制来解决这些问题. ReentrantLock类实现Lock,它具有与sync相同的并发性和内存语义,并且还可以扩展.

在多线程中,有多种方法允许线程按特定顺序执行. 您可以使用线程的join()方法启动一个线程中的另一个线程,并使用另一个线程来完成该线程以继续执行. 为了确保三个线程的顺序,您应该开始最后一个线程(T3调用T2,T2调用T1),以便T1首先完成,T3最后完成.

Yield方法可以挂起当前正在执行的线程对象,并允许其他具有相同优先级的线程执行. 它是一种静态方法,仅保证当前线程放弃CPU使用率,而不能保证其他线程一定可以占用CPU. 进入挂起状态后,可以立即再次执行执行yield()的线程.

ConcurrentHashMap将实际映射分为几个部分,以实现其可伸缩性和线程安全性. 该划分是使用并发获得的. 它是ConcurrentHashMap类构造函数的可选参数. 默认值为16,这样在多线程的情况下可以避免争用.

Java中的信号量是一个新的同步类,它是一个计数信号. 从概念上讲,信号量维护一组权限. 如有必要,在许可证可用之前,将阻塞每个acquire(),然后获取许可证. 每个版本()都会添加一个许可证,该许可证可能会释放阻止获取者. 但是,信号量不是使用实际的许可证对象,而是仅计算可用许可证的数量并采取相应的措施. 信号量通常用于多线程代码中,例如连接池.

这个问题非常棘手,许多程序员会认为任务将阻塞直到线程池队列为空. 实际上,如果无法安排任务的执行时间,则ThreadPoolExecutor的commit()方法将引发RejectedExecutionException.

这两个方法都可以将任务提交到线程池. execute()方法的返回类型为void,这是在Executor接口中定义的,submit()方法可以返回保存计算结果的Future对象,该对象在ExecutorService中定义. 在该接口中,它扩展了Executor接口,其他线程池类(例如ThreadPoolExecutor和ScheduledThreadPoolExecutor)具有这些方法.

阻塞方法意味着程序将始终等待该方法完成而无需执行其他任何操作. ServerSocket的Accept()方法用于等待客户端连接. 这里阻塞意味着在调用结果返回之前,当前线程将被挂起,直到获得结果后才返回. 此外,还有异步和非阻塞方法会在任务完成之前返回.

您可以肯定地给出答案,Swing不是线程安全的,但是即使面试官不问您为什么,您也应该解释该答案的原因. 当我们说swing不是线程安全的时,我们经常提到它的组件. 这些组件不能在多个线程中修改. GUI组件的所有更新必须在AWT线程中完成. Swing提供同步和异步回调方法. 要更新.

Swing API为Java开发人员提供了这两种方法,用于从当前线程而不是事件分发线程更新GUI组件. InvokeAndWait()同步更新GUI组件,例如进度条. 更新进度后,进度栏也需要相应地更改. 如果进度由多个线程跟踪,则调用invokeAndWait()方法以请求事件分派线程相应地更新组件. invokeLater()方法异步调用更新组件.

此问题还提到了摆动和螺纹安全性. 尽管该组件不是线程安全的,但是有些方法可以被多个线程安全地调用,例如repaint(),revalidate(). JTextComponent的setText()方法以及JTextArea的insert()和append()方法也是线程安全的.

这个问题似乎与多线程无关,但是不变性有助于简化已经很复杂的并发程序. 可以共享不可变的对象而无需同步,从而减少了同时访问对象时的同步开销. 但是,Java没有@Immutable批注. 要创建一个不可变的类,您需要执行以下步骤: 通过构造函数初始化所有成员,不提供变量的setter方法,并将所有成员声明为私有. 这不允许直接访问. 要在getter方法中访问这些成员,请勿直接返回对象本身,而是克隆对象并返回对象的副本. 我的文章“如何使对象在Java中不可变”中有详细的教程,阅读后您可以放心.

通常,读写锁是用于提高并发程序性能的锁分离技术的结果. Java中的ReadWriteLock是Java 5中的新接口. ReadWriteLock维护一对关联的锁,一个用于只读操作,一个用于写入. 如果没有写线程,则多个读线程可以同时持有一个读锁. 写锁是排他的. 您可以在JDK中使用ReentrantReadWriteLock来实现此规则. 它最多支持65535个写锁和65535个读锁.

繁忙循环是程序员使用循环使线程等待的地方. 与传统的方法wait(),sleep()或yield()不同,它们都放弃了CPU控制,而busy循环没有放弃CPU,而是运行一个Empty循环. 这样做的目的是保留CPU缓存. 在多核系统中,等待的线程在唤醒时可能会在另一个核中运行,这将重建缓存. 它可用于避免重建缓存并减少等待重建的时间.

这是一个有趣的问题. 首先,volatile和atomic变量看起来相似,但是它们的功能不同. 易变变量可以确保提前关系,即写操作将在后续的读操作之前进行,但不能保证原子性. 例如,如果用volatile修改了count变量,则count ++操作不是原子的. AtomicInteger类提供的原子方法可以使此操作成为原子操作. 例如,getAndIncrement()方法将原子地将当前值递增1,其他数据类型和引用变量也可以执行类似的操作.

java线程死锁例子_java多线程避免死锁_避免线程死锁

这个问题使很多Java程序员感到困惑. 如果您可以通过此提示答案来考虑是否可以解除锁定,则有一点希望将其正确. 不管您的同步块是正常退出还是异常退出,内部线程都会释放锁定,因此我更喜欢同步块而不是锁定接口,因为它不需要我花费精力来释放锁定. 可以通过释放finally块中的锁来实现此功能.

在Java面试中经常会问这个问题,但是面试官对回答这个问题的满意度仅为50%. 一半的人不能编写双重检查锁,一半的人不能告诉隐藏的危险以及Java 1.5如何解决它. 实际上,这是创建线程安全单例的一种旧方法. 首次创建单例实例时,它将尝试使用单个锁进行性能优化,但是在JDK1.4中它太复杂了. 我个人也不喜欢. 无论如何,即使您不喜欢它,也必须找出来,因为它经常被问到.

这是上述问题的后续措施. 如果您不喜欢双重检查锁,并且访问者要求使用其他方法来创建Singleton类,则可以使用JVM的类加载和静态变量初始化功能来创建Singleton实例,或者使用枚举类型来创建Singleton,我喜欢使用这种方法.

我最喜欢这种问题. 我相信您在编写并发代码以提高性能时将遵循某些最佳实践. 我认为大多数Java程序员应该遵循以下三个最佳实践:

给线程起一个有意义的名字.

这使查找错误或查找故障变得容易. OrderProcessor,QuoteProcessor或TradeProcessor比Thread-1更好. 线程2和线程3. 为线程命名一个与其想要完成的任务相关的名称. 所有主要框架,甚至JDK都遵循这种最佳实践.

避免锁定并缩小同步范围

锁定很昂贵,并且上下文切换更加耗时. 尝试最小化使用同步和锁定以减小关键区域. 因此,与同步方法相比,我更喜欢使用同步块,从而可以绝对控制锁.

更多地使用同步类,而更少地使用等待和通知

首先,同步类CountDownLatch,Semaphore,CyclicBarrier和Exchanger简化了编码操作,并且很难通过等待和通知来控制复杂的控制流. 其次,这些类是由最好的公司编写和维护的. 在随后的JDK中,将不断对其进行优化和改进. 使用这些高级同步工具,您可以轻松地优化程序.

更多并发集而更少同步集

这是另一种易于遵循且从中受益匪浅的最佳实践. 并发集合比同步集合更具可伸缩性,因此在并发编程中使用并发集合效果更好. 如果下次需要使用地图,则应首先考虑使用ConcurrentHashMap.

这个问题就像如何强制Java垃圾回收. 目前尚无方法. 尽管可以使用System.gc()进行垃圾回收,但不能保证成功. 无法强制在Java中启动线程. 它由线程调度程序控制,并且Java不发布相关的API.

fork join框架是JDK7中出现的高效工具,Java开发人员可以使用它来充分利用现代服务器上的多处理器. 它是专为可以递归地分为许多子模块的应用程序而设计的,目的是利用所有可用的处理能力来提高程序的性能. fork联接框架的巨大优势在于它使用了一种工作窃取算法,并且可以完成更多任务的工作线程可以从其他线程中窃取任务来执行.

Java程序中的

等待和睡眠会导致某种形式的暂停,它们可以满足不同的需求. wait()方法用于线程间通信. 如果等待条件为真,并且其他线程被唤醒,它将释放锁定. sleep()方法仅释放CPU资源或停止当前线程一段时间,而不会释放锁.


本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/jisuanjixue/article-225918-2.html

相关阅读
    发表评论  请自觉遵守互联网相关的政策法规,严禁发布、暴力、反动的言论

    热点图片
    拼命载入中...