当我们看JDK API什么时候,总是找一些类描述说:,线程安全或线程安全,例如StringBuilder在,么一句,“将StringBuilder 的实例用于多个线程是不安全的。假设须要这种同步,则建议使用StringBuffer
”,那么以下手动创建一个线程不安全的类,然后在多线程中使用这个类,看看有什么效果。

Count.java:

[java] view
plain
copy

  1. public class Count {
  2. private int num;
  3. public void count() {
  4. for(int i = 1; i <= 10; i++) {
  5. num += i;
  6. }
  7. System.out.println(Thread.currentThread().getName() + "-" + num);
  8. }
  9. }

在这个类中的count方法是计算1一直加到10的和,并输出当前线程名和总和。我们期望的是每一个线程都会输出55。

ThreadTest.java:

[java] view
plain
copy

  1. public class ThreadTest {
  2. public static void main(String[] args) {
  3. Runnable runnable = new Runnable() {
  4. Count count = new Count();
  5. public void run() {
  6. count.count();
  7. }
  8. };
  9. for(int i = 0; i < 10; i++) {
  10. new Thread(runnable).start();
  11. }
  12. }
  13. }

这里启动了10个线程,看一下输出结果:

[java] view
plain
copy

  1. Thread-0-55
  2. Thread-1-110
  3. Thread-2-165
  4. Thread-4-220
  5. Thread-5-275
  6. Thread-6-330
  7. Thread-3-385
  8. Thread-7-440
  9. Thread-8-495
  10. Thread-9-550

仅仅有Thread-0线程输出的结果是我们期望的。而输出的是每次都累加的,这里累加的原因以后的博文会说明。那么要想得到我们期望的结果,有几种解决方式:

1. 将Count中num变成count方法的局部变量;

[java] view
plain
copy

  1. public class Count {
  2. public void count() {
  3. int num = 0;
  4. for(int i = 1; i <= 10; i++) {
  5. num += i;
  6. }
  7. System.out.println(Thread.currentThread().getName() + "-" + num);
  8. }
  9. }

2. 将线程类成员变量拿到run方法中,这时count引用是线程内的局部变量;

[java] view
plain
copy

  1. public class ThreadTest4 {
  2. public static void main(String[] args) {
  3. Runnable runnable = new Runnable() {
  4. public void run() {
  5. Count count = new Count();
  6. count.count();
  7. }
  8. };
  9. for(int i = 0; i < 10; i++) {
  10. new Thread(runnable).start();
  11. }
  12. }
  13. }

3. 每次启动一个线程使用不同的线程类,不推荐。

        上述測试,我们发现。存在成员变量的类用于多线程时是不安全的,不安全体如今这个成员变量可能发生非原子性的操作,而变量定义在方法内也就是局部变量是线程安全的。想想在使用struts1时。不推荐创建成员变量,由于action是单例的,假设创建了成员变量。就会存在线程不安全的隐患,而struts2是每一次请求都会创建一个action。就不用考虑线程安全的问题。

所以,日常开发,一般来说,我们需要考虑在多线程环境中的成员变量和全局变量,是否会导致一些问题。

版权声明:本文博客原创文章,博客,未经同意,不得转载。

Java线(一个):线程安全的和不安全的更多相关文章

  1. JAVA - 启动一个线程是用run()还是start()?

    JAVA - 启动一个线程是用run()还是start()? 启动一个线程是调用start()方法,使线程所代表的虚拟处理机处于可运行状态,这意味着它可以由JVM调度并执行.这并不意味着线程就会立即运 ...

  2. 用 Java 写一个线程安全的单例模式(Singleton)?

    请参考答案中的示例代码,这里面一步一步教你创建一个线程安全的 Java 单例类.当我们说线程安全时,意思是即使初始化是在多线程环境中,仍然能保证单个实例.Java 中,使用枚举作为单例类是最简单的方式 ...

  3. java 添加一个线程、创建响应的用户界面 。 演示示例代码

    javajava 添加一个线程.创建响应的用户界面 . 演示示例代码 来自thinking in java 4 21章  部分的代码  夹21.2.11 thinking in java 4免费下载: ...

  4. Java中一个线程只有六个状态。至于阻塞、可运行、挂起状态都是人们为了便于理解,自己加上去的。

    java中,线程的状态使用一个枚举类型来描述的.这个枚举一共有6个值: NEW(新建).RUNNABLE(运行).BLOCKED(锁池).TIMED_WAITING(定时等待).WAITING(等待) ...

  5. java停止一个线程

    Thread类中有start(), stop()方法,不过stop方法已经被废弃掉. 平时其实也有用过,共享一个变量,相当于标志,不断检查标志,判断是否退出线程 如果有阻塞,需要使用Thread的in ...

  6. Java里一个线程两次调用start()方法会出现什么情况

    Java的线程是不允许启动两次的,第二次调用必然会抛出IllegalThreadStateException,这是一种运行时异常,多次调用start被认为是编程错误. 如果业务需要线程run中的代码再 ...

  7. Java自学-多线程 启动一个线程

    Java 创建一个线程的三种方式 多线程即在同一时间,可以做多件事情. 创建多线程有3种方式,分别是继承线程类,实现Runnable接口,匿名类 步骤 1 : 线程概念 首先要理解进程(Process ...

  8. 线程池如何复用一个线程-- ThreadPoolExecutor的实现(未完)

    任务是一组逻辑工作单元,而线程则是使任务异步执行的机制.在Java中,Runnable对象代表一个任务,Thread对象负责创建一个线程执行这个任务. 前提:1. 程序需要处理大量任务 2. 任务的执 ...

  9. java多线程之:创建开启一个线程的开销

    ---->关于时间,创建线程使用是直接向系统申请资源的,这里调用系统函数进行分配资源的话耗时不好说.---->关于资源,Java线程的线程栈所占用的内存是在Java堆外的,所以是不受jav ...

随机推荐

  1. linux--shell script

    下面是最近学习shell script的一些知识点总结 ***博客园-邦邦酱好***   1.介绍shell是一个文字接口,让我们与系统沟通.shell script就是针对shell所写的脚本.它就 ...

  2. SWT的CheckBoxTreeView的上级菜单与下级菜单的选中的实现

    是不是很神奇? treeViewer.addCheckStateListener(new ICheckStateListener() { @Override public void checkStat ...

  3. JS CSS 网页 简单 右侧 悬浮

    <!--右侧效果--> <script> $().ready(function() { $(".orm").hover(function() { $(thi ...

  4. 不用Root权限获取已经安装的Apk安装包

    在安卓设备上安装的apk都会被保留一份在/data/app目录下,但是该目录对于普通用户来说只有可执行权限,是无法访问的. 但是其子文件具有可读权限. 意思也就说我们直接去查看/data/app这个目 ...

  5. python学习笔记之七:魔法方法,属性

    在python中,有的名称会在前面和后面加上两个下划线,由这些名字组成的集合所包含的方法称为魔法方法(或者是特殊方法).如果对象实现了这些方法中的某一个,那么这个方法会在特殊的情况下(确切地说是根据名 ...

  6. Android实战技术:IPC方式简介教程

    非实时,通知性的方式 第一种方式就是Intent,Intent可以非常方便的通讯,但是它是非实时的,无法进行实时的像函数调用那样的实时的通讯. 实时的函数调用 但是IPC的根本目的还是为了实现函数的调 ...

  7. 排序算法c语言描述---冒泡排序

    排序算法系列学习,主要描述冒泡排序,选择排序,直接插入排序,希尔排序,堆排序,归并排序,快速排序等排序进行分析. 文章规划: 一.通过自己对排序算法本身的理解,对每个方法写个小测试程序. 具体思路分析 ...

  8. [Sqlite]--&gt;Java采用jdbc联系Sqlite各种特定的工艺数据库的数据操作

    引:     1, Sqlite在Windows.Linux 和 Mac OS X 上的安装过程     2.嵌入式数据库的安装.建库.建表.更新表结构以及数据导入导出等等具体过程记录     3,嵌 ...

  9. jvisualvm远程监控Tomcat

    网上已经有很多这方面的资料,但有些很杂乱,这里做了整理总结. 一.Java VisualVM 概述 对于使用命令行远程监控jvm 太麻烦 . 在jdk1.6 中 Oracle 提供了一个新的可视化的. ...

  10. 深度this指针

    深入探讨this指针   为了写这篇文章.准备了好长时间,翻遍了箱底的书籍.可是如今还是不敢放开手来写,战战兢兢. 不是操心自己写错.而是唯恐自己错误误导别人.同一时候也希望这篇文章能给你一点收获.既 ...