java线程(二)
线程范围变量
我们知道线程在cpu上的使用权并不是长时间的,因为计算机的cpu只有一个,而在计算上运行的进程有很多,线程就更不用说了,所以cpu只能通过调度来上多个线程轮流占用cpu资源运行,且为了保障多个进程能够同时运行。cpu只能通过频繁调度线程来是的每个线程在几乎同一时间内都能得到cpu的使用权来执行代码来保证程序能够正常运行,所以cpu的调度频率是很快的。那么问题来了。如下代码:
package cn.wz.traditional.wf; import javafx.scene.chart.PieChart; /**
* Created by WangZhe on 2017/5/4.
*/
public class ThraedLocalTest {
public static void main(String[] args) {
new Thread(new Runnable() {
public void run() {
A.age=5;
A.age+=10;
System.out.println(A.age);
}
}).start(); new Thread(new Runnable() {
public void run() {
A.age=7;
}
}).start();
}
static class A{
static Integer age=5;
private Integer data;
public A(Integer data){
this.data=data;
}
public void sayHi(){
data+=10;
System.out.println(data); }
public void sayHello(){
data=5;
}
}
}
demo
上面这段代码创建了两个线程,第一个线程将a的原始值加10后输出,第二个线程将a赋值为7,但在不改变代码的前提下多次执行后发现这段代码出现了两种运行结果。如图所示。


这种问题正是由于cpu调度线程所引起的,当其结果为15时使我们所预期的效果,那怎样来确保其结果和我们预期的效果一致呢?废话不多说了直接上代码
package cn.wz.traditional.wf; import javafx.scene.chart.PieChart; import java.util.HashMap;
import java.util.Map; /**
* Created by WangZhe on 2017/5/4.
*/
public class ThraedLocalTest {
public static void main(String[] args) {
new Thread(new Runnable() {
public void run() {
A a=new A(5);
a.sayHi(5);
}
}).start(); new Thread(new Runnable() {
public void run() {
A a=new A(5);
a.sayHello();
}
}).start();
}
static class A{
static Map<String,Integer> ages=new HashMap<String, Integer>();//创建一个键值集合一线程id为key值来存放线程范围的变量
private Integer data;
public A(Integer data){
this.data=data;
}
public void sayHi(Integer age){
ages.put(String.valueOf(Thread.currentThread().getId()),age);
Integer data= ages.get(String.valueOf(Thread.currentThread().getId()));
data+=10;
ages.put(String.valueOf(Thread.currentThread().getId()),data);
System.out.println(ages.get(String.valueOf(Thread.currentThread().getId()))); }
public void sayHello(){
ages.put(String.valueOf(Thread.currentThread().getId()),7);
}
}
}
在之前代码的基础上增加一个map集合来保存线程范围的变量数据,以当前线程的id为key值来确保每次取到的值都是当前线程的值。但是这种方法出现了大量的冗余代码,每次取值赋值都很费劲,其实Java API提供了Threadlocal类来保存线程范围的变量,下面是使用Threadlocal类之后的代码.
package cn.wz.traditional.wf; import javafx.scene.chart.PieChart; import java.util.HashMap;
import java.util.Map; /**
* Created by WangZhe on 2017/5/4.
*/
public class ThraedLocalTest {
public static void main(String[] args) {
new Thread(new Runnable() {
public void run() {
A a=new A();
a.sayHi(5);
}
}).start(); new Thread(new Runnable() {
public void run() {
A a=new A();
a.sayHello();
}
}).start();
}
static class A{
ThreadLocal<Integer> tl=new ThreadLocal<Integer>();
public void sayHi(Integer age){
tl.set(age);
Integer data = tl.get();
data+=10;
tl.set(data);
System.out.println(tl.get());
}
public void sayHello(){
tl.set(7);
}
}
}
使用Threadlocal之后的代码
如上面代码所示ThreadLocal类在赋值和获取值时比我们之前写的代码方便了许多并不需要提供key值就能进行操作,其实ThreadLocal类的实现和我们之前的实现差不多的差不多,下面介绍下threadLocal类的方法实现,
ThreadLocal 类方法详解
ThreadLocal类提供了一下四种方法供程序员调用,下面为大家介绍每个方法的实现。

InitialValue()方法,该方法在对象调用get方法时,之前并没有调用过set方法赋值的情况下调用该方法返回null值,如图所示,
set()方法,该方法是为线程范围变量的赋值方法,其内容如下:

GetMap()方法内容


CreateMap方法内容

get方法:给方法是获取线程范围变量的方法,我们已经知道了线程范围变量保存在一个以ThreadLocal实例为key值得map集合中所以对此这里不再进行赘述了,我们着重关注一下调用get之前并没有使用set方法为集合中该项赋值的情况,
如下所示:


remove方法:该方法是移除当前线程中该ThreadLocal实例对应的线程范围变量值,注意,并不是当前线程的所有范围变量值,如图所示

总结:
java API提供ThreadLocal类来保存线程范围变量,一个ThreadLocal对象在一个线程上只能绑定一个线程范围变量,但一个ThreadLocal对象可以为多个不同的线程绑定线程范围变量值。
java线程(二)的更多相关文章
- Java线程(二):线程同步synchronized和volatile
上篇通过一个简单的例子说明了线程安全与不安全,在例子中不安全的情况下输出的结果恰好是逐个递增的(其实是巧合,多运行几次,会产生不同的输出结果),为什么会产生这样的结果呢,因为建立的Count对象是线程 ...
- java 线程二
一.线程的优先级别 线程优先级别的使用范例: 1 package cn.galc.test; 2 3 public class TestThread6 { 4 public static void m ...
- Java线程专栏文章汇总(转)
原文:http://blog.csdn.net/ghsau/article/details/17609747 JDK5.0之前传统线程 Java线程(一):线程安全与不安全 Java线程 ...
- Java线程专栏文章汇总
转载自 http://blog.csdn.net/ghsau/article/details/17609747 JDK5.0之前传统线程 Java线程(一):线程安全与不安全 J ...
- Java线程池使用和分析(二) - execute()原理
相关文章目录: Java线程池使用和分析(一) Java线程池使用和分析(二) - execute()原理 execute()是 java.util.concurrent.Executor接口中唯一的 ...
- java线程池技术(二): 核心ThreadPoolExecutor介绍
版权声明:本文出自汪磊的博客,转载请务必注明出处. Java线程池技术属于比较"古老"而又比较基础的技术了,本篇博客主要作用是个人技术梳理,没什么新玩意. 一.Java线程池技术的 ...
- Java线程池ThreadPoolExecutor使用和分析(二) - execute()原理
相关文章目录: Java线程池ThreadPoolExecutor使用和分析(一) Java线程池ThreadPoolExecutor使用和分析(二) - execute()原理 Java线程池Thr ...
- 性能测试三十二:监控之Java线程监控
线程的五种状态 * 新建:new * 运行:runnable * 等待:waitting(无限期等待),timed waitting(限期等待) * 阻塞:blocked * 结束:terminate ...
- Java线程池详解(二)
一.前言 在总结了线程池的一些原理及实现细节之后,产出了一篇文章:Java线程池详解(一),后面的(一)是在本文出现之后加上的,而本文就成了(二).因为在写完第一篇关于java线程池的文章之后,越发觉 ...
- 【Java并发专题之二】Java线程基础
使用线程更好的提高资源利用率,但也会带来上下文切换的消耗,频繁的内核态和用户态的切换消耗,如果代码设计不好,可能弊大于利. 一.线程 进程是分配资源的最小单位,线程是程序执行的最小单位:线程是依附于进 ...
随机推荐
- SEVERE: Error configuring application listener of class org.springframework.web.context.ContextLoaderListener错误
错误信息:SEVERE: Error configuring application listener of class org.springframework.web.context.Context ...
- Struts2之Action与配置文件
一.Struts2配置文件 1.struts.properties 在学习Action之前先学下Struts2的配置文件,与Struts2相关的配置文件有好几个,常用的有Struts.xml,web. ...
- 极客君教你破解隔壁妹子的wifi密码,成功率高达90%
首先,给大家推荐一个我自己维护的网站: 开发者网址导航:http://www.dev666.com/ 破解wifi密码听起来很复杂,实际上也不是非常的复杂,极客君(微信公众帐号:极客峰)今天教大家如何 ...
- windows32位安装MYSQL-python1.2.3
建议不要用pip安装MYSQL-python,因为会自动选择MYSQL-python1.2.5这个版本,但是这个版本不支持windows 32位系统. 1.首先安装VS2008,因为要依赖VC9.0编 ...
- iOS 10 语音识别Speech Framework详解
最近做了一个项目,涉及到语音识别,使用的是iOS的speech Framework框架,在网上搜了很多资料,也看了很多博客,但介绍的不是很详细,正好项目做完,在这里给大家详解一下speech Fram ...
- HDU-2298 Toxophily (三分法入门系列)
题意: 意大利炮射出炮弹的速度为v,求在(0,0)击中(x,y)处的目标,发射炮弹的角度. 题解: 设f(α)表示角度为α时, f(α) = vsin(α) * t - 4.9 * t * t ① ...
- 微信小程序评分功能
很多做过电商项目的朋友会经常用到评分的功能,我这里正好写了一个例子,发出来分享一下: 我写的是5分满分制的,首先,准备3个图片, ,像这样的,分别代表分数为0,0.5,1 时的状态, 效果图:(以3. ...
- 老李推荐:第8章7节《MonkeyRunner源码剖析》MonkeyRunner启动运行过程-小结
老李推荐:第8章7节<MonkeyRunner源码剖析>MonkeyRunner启动运行过程-小结 poptest是国内唯一一家培养测试开发工程师的培训机构,以学员能胜任自动化测试,性 ...
- 图的基本算法(BFS和DFS)(转载)
图是一种灵活的数据结构,一般作为一种模型用来定义对象之间的关系或联系.对象由顶点(V)表示,而对象之间的关系或者关联则通过图的边(E)来表示. 图可以分为有向图和无向图,一般用G=(V,E)来表示图. ...
- jmeter 使用jmeter 录制web脚本
1.打开jmeter.鼠标右击工作台.添加HTTP代理服务器 2.设置端口号.目标控制器.分组 3.添加查看结果树 4.点击启动.确定完成 5.打开浏览器直接进行操作.就可以看到所录制的脚本信息