线程魔术技巧:Java线程可以做的5件事

Java线程最鲜为人知的事实和用例是什么?

线程 有些人喜欢爬山,有些人喜欢跳伞。 我,我喜欢Java。 我喜欢它的一件事是,您永不停止学习。 您每天使用的工具通常可以向您展示全新的方面,以及您还没有机会看到的方法和有趣的用例。 例如线程。 实际线程。 或者更好的是,Thread类本身。 当我们使用高可伸缩性系统时,并发编程永远不会停止挑战,但是现在我们将讨论一些不同的东西。

在这篇文章中,您将看到线程支持的一些鲜为人知但有用的技术和方法。 无论您是初学者,高级用户还是Java专业开发人员,都请尝试查看其中哪些已为您所知,以及哪些是新产品。 关于线程,您还有其他值得一提的地方吗? 我希望在下面的评论中听到它。 让我们开始吧。

初学者

1.线程名称

应用中的每个线程都有一个名称,即构造该线程时为其生成的简单Java字符串。 默认名称值从“ Thread-0”到“ Thread-1”,“ Thread-2”,依此类推。 现在出现了更有趣的部分–线程公开了两种可用来设置其名称的方法:

1.线程构造函数,这是最简单的一个:

class SuchThread extends Thread {Public void run() {System.out.println ("Hi Mom! " + getName());}}SuchThread wow = new SuchThread("much-name");

2.线程名称设置器:

wow.setName(“Just another thread name”);

是的,线程名是可变的。 因此,除了在实例化实例名称时设置自定义名称外,我们还可以在运行时进行更改。 名称字段本身设置为简单的String对象。 这意味着它最多可以包含2³¹-1个字符(Integer.MAX_VALUE)。 我说的绰绰有余。 请注意,该名称不像唯一ID,因此线程可以共享相同的名称。 另外,不要尝试将null作为名称传递,除非您希望引发异常(不过“ null”是可以的,我没有判断!)。

使用线程名称进行调试

因此,现在您可以访问线程名称,遵循自己的一些命名约定,可以在发生问题时使您的生活变得更加轻松。 “ Thread-6”听起来有些无情,我相信您可以想到一个更好的名字。 在处理用户请求时,将其与自分配的事务ID结合在一起,将其附加到线程的名称上,您将大大减少错误解决时间。

保留在此处的一个好习惯是确保您在应用程序的每个线程的入口点生成一个UUID,并在请求在节点,进程和线程之间传递时保持一致。 让我们看一下这个示例,某个线程池中的一个工作线程挂起了太长时间。 您运行jstack仔细查看,然后看到以下内容:

“pool-1-thread-1″ #17 prio=5 os_prio=31 tid=0x00007f9d620c9800
nid=0x6d03 in Object.wait() [0x000000013ebcc000]

好的,“ pool-1-thread-1”,为什么这么严重? 让我们更好地了解您,并想出一个更合适的名称:

Thread.currentThread().setName(Context + TID + Params + current Time, ...);

现在,当我们再次运行jstack时,情况看起来好多了:

”Queue Processing Thread, MessageID: AB5CAD, type:
AnalyzeGraph, queue: ACTIVE_PROD, Transaction_ID: 5678956,
Start Time: 30/12/2014 17:37″ #17 prio=5 os_prio=31 tid=0x00007f9d620c9800
nid=0x6d03 in Object.wait() [0x000000013ebcc000]

我们知道线程在阻塞时正在做什么,并且还拥有启动所有线程的事务ID。 您可以追溯步骤,重现错误,隔离并解决它。 要了解更多有关使用jstack的酷方法的信息,您可以在此处查看这篇文章。

2.线程优先级

优先级是另一个有趣的领域线程。 线程的优先级是介于1(MIN_PRIORITY)到10(MAX_PRIORITY)之间的值,主线程的默认值为5(NORM_PRIORITY)。 每个新线程都获得其父级的优先级,因此,如果您不手动使用它,则所有线程的优先级都可能设置为5。这也是Thread类的一个经常被忽略的字段,我们可以对其进行访问和操作。通过方法getPriority()setPriority() 。 无法在线程构造函数中进行设置。

谁仍然需要优先考虑?

当然,并非所有线程都是平等创建的,有些线程需要您的CPU立即关注,而其他线程只是后台任务。 优先级用于向OS线程调度程序发出信号。 在Takipi,我们开发了一个错误跟踪和分析工具,为用户处理新异常的线程将获得MAX_PRIORITY,而处理诸如报告新部署等任务的线程将获得较低的优先级。 可能希望优先级较高的线程从与JVM一起使用的线程调度程序中获得更多时间。 好吧,并非总是如此。

每个Java线程都会在OS级别上打开一个新的本机线程,并且您设置的Java优先级会以不同的方式转换为每个平台的本机优先级。 在Linux上,在运行应用程序时,还必须包括“ -XX:+ UseThreadPriorities”标志,以便将它们考虑在内。 话虽如此,线程优先级仍然只是您提供的建议。 与本机Linux优先级相比,它们甚至没有涵盖整个值范围(1..99,以及线程范围的影响范围在-20..20之间)。 主要要点是保持自己的逻辑以确保优先级在每个线程获得的CPU时间中得到反映的重要性,但是不建议仅依靠优先级。

弗雷德·泰尔斯

高级

3.线程本地存储

这与我们在这里谈论的其他生物有些不同。 ThreadLocal是一个从Thread类( java.lang.ThreadLocal )实现的概念,但是为每个线程存储唯一的数据。 就像它上面说的那样,它为您提供了线程本地存储,这意味着您可以创建每个线程实例唯一的变量。 与您拥有线程名称或优先级的方式类似,您可以创建自定义字段,使其看起来像是Thread类的成员。 那不是很酷吗? 但是,我们不要太激动 ,前面有一些警告。

建议以以下两种方式之一创建ThreadLocal:作为静态变量或单例的一部分,在该局部不必是静态的。 请注意,它位于全局范围内,但在每个能够访问它的线程中局部执行。 这是一个ThreadLocal变量的示例,该变量持有我们自己的数据结构以便于访问:

public static class CriticalData
{public int transactionId;public int username;
}public static final ThreadLocal<CriticalData> globalData =new ThreadLocal<CriticalData>();

一旦有了ThreadLocal,就可以使用globalData.set()globalData.get()对其进行访问

全球? 一定是邪恶的

不必要。 ThreadLocal变量可以保留事务ID。 当您有一个未捕获的异常使您的代码冒泡时,这可以派上用场。 一个好的做法是设置一个UncaughtExceptionHandler ,我们也可以通过Thread类获得它,但必须自己实现。 一旦我们到达那个阶段,关于实际上是什么使我们到达那里的提示就不多了。 我们剩下的是Thread对象,当堆栈框架关闭时,无法访问将我们带到那里的任何变量。 在我们的UncaughtExceptionHandler中,随着线程的最后呼吸,ThreadLocal几乎是我们剩下的仅有的东西之一。

我们可以本着以下精神做一些事情:

System.err.println("Transaction ID " + globalData.get().transactionId);

就像这样,我们为错误添加了一些有价值的上下文。 使用ThreadLocal的一种更富创意的方法是通过分配指定的内存块,以供工作线程反复用作缓冲区。 当然,这可能会很有用,具体取决于您在内存的哪一侧与CPU开销之间的权衡。 也就是说,要注意的是滥用我们的内存空间。 只要特定线程存在,ThreadLocal就存在于特定线程中,除非将其释放或线程死亡,否则不会被垃圾回收。 因此,在使用它时最好小心并保持简单。

4.用户线程和守护程序线程

回到我们的线程类。 我们应用中的每个线程都会收到“用户”或“守护程序”状态。 换句话说,前景或后台线程。 默认情况下,主线程是用户线程,每个新线程都获得创建它的线程的状态。 因此,如果将线程设置为守护程序,则它创建的所有线程也将被标记为守护程序。 当您的应用程序中仅剩下正在运行的线程处于守护程序状态时,该进程关闭。 要进行测试,检查和更改线程状态,我们有布尔值.setDaemon(true).isDaemon()方法。

什么时候设置守护进程线程?

当线程对线程的结束不是很关键时,应将其状态更改为守护进程,以便进程可以关闭。 它消除了正确关闭线程,立即停止所有操作并让它快速结束的麻烦。 另一方面,当有一个线程运行的操作必须正确结束时,否则将发生不良情况,请确保将其设置为用户线程。 关键事务可以是例如数据库条目或完成不间断的更新。

专家

5. Java处理器亲和力

这部分使我们更接近代码与金属相遇的硬件。 处理器关联允许您将线程或进程绑定到特定的CPU内核。 这意味着无论何时执行该特定线程,它都将专门在一个特定内核上运行。 通常情况下,操作系统线程调度程序将根据其自己的逻辑担当此角色,可能会考虑我们前面提到的线程优先级。

讨价还价的筹码是CPU缓存。 如果一个线程只在一个特定的内核上运行,则很有可能会喜欢将所有数据准备好在缓存上。 当数据已经存在时,无需重新加载它。 您节省的微秒数可以被更好地利用,并且代码实际上将在该时间运行,从而更好地利用分配的CPU时间。 尽管确实在操作系统级别进行了一些优化,并且硬件体系结构当然也起着重要作用,但是使用亲和力可以消除线程切换内核的机会。

由于这里有许多因素在起作用,因此确定处理器亲和力将如何影响您的吞吐量的最好方法是接受测试的习惯。 尽管它可能并不总是会好得多,但是您可能会遇到的好处之一就是吞吐量稳定。 亲和力策略可以降低到手术水平,具体取决于获得的收益。 高频交易行业将是这类事情最重要的地方之一。

测试处理器亲和力

Java没有对处理器相似性的本机支持,但这当然还没有结束。 在Linux上,我们可以使用tasket命令设置进程亲和力。 假设我们有一个Java进程正在运行,我们想将其固定到特定的CPU:

taskset -c 1 “java AboutToBePinned”

或者,如果它已经在运行:

taskset -c 1 <PID>

现在,要进入线程级别,我们需要插入一些新代码。 幸运的是,有一个开源库可以帮助我们做到这一点: Java-Thread-Affinity 。 由OpenHFT的Peter Lawrey撰写,这可能是最简单的方法。 让我们看一个固定线程的简单示例,更多信息可以在该库的GitHub存储库中找到:

AffinityLock al = AffinityLock.acquireLock();

就是这样。 GitHub上提供了用于获取锁的更高级选项,其中考虑了选择特定内核的不同策略。

结论

我们已经看到了5种查看线程的方法:线程名称,线程本地存储,优先级,守护程序线程和相似性。 希望这有助于您每天处理新事物,并很高兴听到您的评论! 还有哪些其他线程处理方法可以适用?

翻译自: https://www.javacodegeeks.com/2015/01/thread-magic-tricks-5-things-you-never-knew-you-can-do-with-java-threads.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/361117.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

强制删除tfs未迁入项的两个方法。

方法1&#xff1a; 打开Vs2008的命令提示&#xff1a; 查看用户的工作区&#xff1a; 输入&#xff1a; Tf workspaces /owner:所有者或* /server:服务器名称或IP ex: tf workspaces /owner:stcct(所有者) /server:203.156.1.100(Ip地址) 删除用户的未迁入项&#xff1a; 输…

VUE 全选

<div id"vue_det"> <p>全选:</p> <input type"checkbox" id"checkbox" v-model"checked" change"changAllChecked"/> <label for"checkbox"> {{checked}} <…

RabbitMQ –使用Spring集成Java DSL串行处理消息

如果您曾经需要使用RabbitMQ来串行处理消息&#xff0c;并且有一群监听器来处理消息&#xff0c;那么我所看到的最好方法是在监听器上使用“独占消费者”标志&#xff0c;每个监听器上有1个线程来处理消息。 专用使用者标志可确保只有1个使用者可以从特定队列中读取消息&#…

添加删除约束脚本 ::fn_get_sql

添加约束&#xff1a;alter table table1 add constraint pk_name primary key (name) --添加主健约束,名称作为主健&#xff1b; alter table table1 add constraint pk_name unique (name) --添加唯一约束,…

jquery 实现 点击把数据移动右侧 点击再次移回到左侧

2018年第一发 希望新的一年和大家一下学习更多知识 JS&#xff1a;//把数据左边挪到了右边&#xff0c;再从右边移动回来function moveOption(e1, e2){ $("#" e1 " option").each(function(){ if($(this).is(:selected)){ var oVal…

企业Java中事务隔离级别的初学者指南

介绍 基于ACID事务属性的关系数据库强一致性模型。 在本文中&#xff0c;我们将阐明对资源本地事务和JTA事务使用不同的事务隔离级别和各种配置模式的背后原因。 隔离和一致性 在关系数据库系统中&#xff0c;原子性和持久性是严格的属性&#xff0c;而一致性和隔离性或多或少…

点击左侧跳到右侧

效果图 JS部分 function moveOption(e1, e2){ try{ for(var i0;i<e1.options.length;i ){ if(e1.options[i].selected){ var e e1.options[i]; e2.options.add(new Option(e.text, e.value)); e1.remove(i); iii-1 } } } catch(e){}} HTML以及CSS部分 <for…

好的微服务架构=企业服务总线(ESB)的灭亡?

这些天&#xff0c;似乎每个人都在谈论微服务。 您可以在数百篇文章和博客文章中读到很多有关该主题的文章&#xff0c;但是我建议的出发点是Martin Fowler的这篇文章 &#xff0c; 该文章引发了有关这种新建筑概念的大量讨论。 本文介绍了创建良好的微服务体系结构所面临的挑战…

移动端UC /QQ 浏览器的部分私有Meta 属性

<meta name"format-detection" content "telephoneno"/> 格式检测 禁止识别我们页面中的数字&#xff0c;防止把其当作电话识别&#xff0c;emailno 禁止识别邮箱 IOS设备对META的私有属性 <meta name"apple-mobile-web-app-capable&qu…

IDC关于使用JBoss Fuse的商业价值的报告(与Apache Camel一起使用)

这只是一篇博客文章&#xff0c;具有更多的商业性质&#xff0c;但是您不能一无所有。 实际上&#xff0c;这也是使Apache Camel保持活力并保持良好状态的原因&#xff0c;这还归功于其商业上的成功。 希望从JBoss Fuse之类的产品中寻找有关在商业上使用Apache Camel的附加值的…

书评:精通Lambda:多核世界中的Java编程

从版本8开始&#xff0c;λ编程&#xff08;lambda编程&#xff09;终于在Java世界中引入。此功能将在很大程度上改变Java开发人员的编程方式以及针对样板代码的新“武器”。 Java 8通过引入新的Stream API&#xff0c;大部分已将函数式编程应用在Collections API中。 此外&…

js框架

PS&#xff1a;https://www.cnblogs.com/zx0303/p/js-liuxingkuangjia.html 下边这张表简述了js目前的流行框架的优点: AngularJ.js 由google开发&#xff0c;2009年首次发布 很流行的前端框架使用Angular.js创建第一个UI&#xff0c;成本很…

Spring-Quartz (一)

摘自&#xff1a; http://www.blogjava.net/Jay2009/archive/2009/03/25/259176.htmlSpring为创建Quartz的Scheduler、Trigger和JobDetail提供了便利的FactoryBean类&#xff0c;以便能够在Spring 容器中享受注入的好处。此外Spring还提供了一些便利工具类直接将Spring中的Bean…

如何在Java Reflection中的类下获取所有方法信息?

本文以我以前的文章为基础 。 在本文中&#xff0c;我们将看到如何使用Java Reflection检索类相关信息。 我们将重点介绍方法名称。 注意&#xff1a;我将创建一个单独的反射器实用程序类&#xff0c;在该类中&#xff0c;我们在其构造函数中输入一个目标类&#xff0c;然后使…

在Java EE 7上骑骆驼–带有Swagger文档的REST服务

骆驼开箱即用。 Swagger集成就是其中之一。 不幸的是&#xff0c;大多数已经存在的功能都严重依赖于Spring。 但这并不能阻止我们在普通的Java EE 7应用程序中使用它们&#xff0c;因为有时它只是服务器的轻量级变体。 但我不想再对此进行讨论。 相反&#xff0c;我认为在所有情…

怎么隐藏滚动条又能滚动

1 <!DOCTYPE html>2 <html lang"en">3 <head>4 <meta charset"UTF-8">5 <title>滚动条隐藏</title>6 <style>7 body, ul, li {8 margin: 0;9 padding: 0; 10 …

Eclipse to android

JDK Eclipse Android SDK ADT 1 必须软件 Java JDK SE 1.6 (jdk-7u9-windows-i586.exe) Eclipse (Eclipse IDE for Java Developers) Google Android SDK (android-sdk_r15-windows.zip) ADT (ADT-15.0.0.zip) 如果找不到可参考&#xff1a; http://blog.csdn.net/zhenyong…

用多态和组合替换多个条件

这是一种众所周知的重构模式&#xff0c;可以将条件条件替换为多态性。 如果您不熟悉该模式&#xff0c;可以在此处查看 。 但是&#xff0c;一旦该类中有多个条件检查所基于的字段&#xff0c;该基本解决方案便会开始崩溃。 我们将研究一些有关如何使用这些可能性的想法。 有…

canvas画饼图

<style> body { background: black; text-align: center; } #cans { background: white; } </style> <script> function disToRad(n){//将度数表示弧度计算的方法 return n*Math.PI/180;//π用PI表示&#xff0c;π180&#xff0c;所以1PI/180 } w…

Web设计趋势分析

本文译自网站设计公司weavora.com&#xff0c;介绍了在他们眼里 8 个 Web 设计趋势&#xff1a;单页面、用照片做背景、色块设计、超大号的图片、聚焦简洁、响应式设计、视差滚动、强调字体&#xff0c;每个趋势后面都附了数个案例&#xff0c;相信对网站设计师会有一定的参考价…