在JDK API中,总会发现一些类说明写着,线程安全或者线程不安全。如StringBuffer文档中写到“可将字符串缓冲区安全地用于多个线程可以在必要时对这些方法进行同步,因此任意特定实例上的所有操作就好像是以串行顺序发生的,该顺序与所涉及的每个线程进行的方法调用顺序一致......从 JDK 5 开始,为该类补充了一个单个线程使用的等价类,即StringBuilder。与该类相比,通常应该优先使用 StringBuilder 类,因为它支持所有相同的操作,但由于它不执行同步,所以速度更快。”那么下面试验一下,看看有什么效果。
public class PrintString { private static String[] cstring = { "a", "b", "c", "d", "e", "f", "g" }; private StringBuilder builder = new StringBuilder(); public void print() { for (int i = 0; i < cstring.length; i++) { builder.append(cstring[i]); } System.out.println(Thread.currentThread().getName() + "-" + builder); } } public class ThreadTest { public static void main(String[] args) { Runnable runnable = new Runnable() { PrintString printer = new PrintString(); public void run() { printer.print(); } }; for (int i = 0; i < 5; i++) { new Thread(runnable).start(); } } }
结果如下:
Thread-0-abcdefg Thread-1-abcdefgabcdefg Thread-2-abcdefgabcdefgabcdefg Thread-3-abcdefgabcdefgabcdefgabcdefg Thread-4-abcdefgabcdefgabcdefgabcdefgabcdefg
只有Thread-0线程输出的结果是我们期望的,而输出的是每次都追加的,因为建立的PrintString对象是线程共享的,一个线程改变了其成员变量builder值,下一个线程正巧读到了修改后的builder,所以会追加输出。那么要想得到我们期望的结果,有几种解决方案:
1,将StringBuilder builder变为方法的局部变量。
public void print() { StringBuilder builder = new StringBuilder(); for (int i = 0; i < cstring.length; i++) { builder.append(cstring[i]); } System.out.println(Thread.currentThread().getName() + "-" + builder); }
2,将线程类成员变量拿到run方法中,这时PrintString printer引用是线程内的局部变量;
public static void main(String[] args) { Runnable runnable = new Runnable() { public void run() { PrintString printer = new PrintString(); printer.print(); } }; for (int i = 0; i < 5; i++) { new Thread(runnable).start(); } }
上述测试,我们发现,存在线程不安全的成员变量的类用于多线程时是不安全的,不安全体现在这个线程不安全的成员变量可能发生非原子性的操作,而变量定义在方法内也就是局部变量是线程安全的。在使用struts1时,不推荐创建成员变量,因为action是单例的,如果创建了成员变量,就会存在线程不安全的隐患,而struts2是每一次请求都会创建一个action,就不用考虑线程安全的问题。所以,日常开发中,通常需要考虑成员变量或者说全局变量在多线程环境下,是否会引发一些问题。
相关推荐
Java线程:概念与原理 Java线程:创建与启动 Java线程:线程栈模型与线程的变量 Java线程:线程状态的转换 Java线程:线程的同步与锁 Java线程:线程的交互 Java线程:线程的调度-休眠 Java线程:线程的调度-优先级 ...
Java线程:概念与原理 Java线程:创建与启动 Java线程:线程栈模型与线程的变量 Java线程:线程状态的转换 Java线程:线程的同步与锁 Java线程:线程的交互 Java线程:线程的调度-休眠 Java线程:线程的调度-...
Java线程:概念与原理 Java线程:创建与启动 Java线程:线程栈模型与线程的变量 Java线程:线程状态的转换 Java线程:线程的同步与锁 Java线程:线程的交互 Java线程:线程的调度-休眠 Java线程:线程的调度-优先级 ...
Java线程:概念与原理 2 一、操作系统中线程和进程的概念 2 二、Java中的线程 3 三、Java中关于线程的名词解释 3 四、线程的状态转换和生命周期 4 Java线程:创建与启动 7 Java线程:线程名称的设定及获取 10 Java...
适合练手、课程设计、毕业设计的Java项目源码:多线程与线程安全实践-基于Http协议的断点续传.rar 适合练手、课程设计、毕业设计的Java项目源码:多线程与线程安全实践-基于Http协议的断点续传.rar 适合练手、课程...
Java线程:概念与原理 Java线程:创建与启动 Java线程:线程状态的转换 Java线程:线程的同步与锁 一、同步问题提出 二、同步和锁定 三、静态方法同步 四、如果线程不能不能获得锁会怎么样 五、何时需要同步...
Java多线程与线程安全实践Java多线程与线程安全实践Java多线程与线程安全实践Java多线程与线程安全实践Java多线程与线程安全实践Java多线程与线程安全实践Java多线程与线程安全实践Java多线程与线程安全实践Java多...
电子书相关:包含4个有关JAVA线程的电子书(几乎涵盖全部有关线程的书籍) OReilly.Java.Threads.3rd.Edition.Sep.2004.eBook-DDU Java Thread Programming (Sams) java线程第二版中英文 java线程第二版中英文 ...
java 多线程 哲学家思考问题 java 多线程 哲学家思考问题 ...java 多线程 哲学家思考问题java 多线程 哲学家思考问题java 多线程 哲学家思考问题java 多线程 哲学家思考问题 java 多线程 哲学家思考问题
Java线程讲解Java线程讲解Java线程讲解Java线程讲解Java线程讲解Java线程讲解Java线程讲解Java线程讲解Java线程讲解Java线程讲解
Java线程Java线程Java线程Java线程Java线程Java线程Java线程Java线程Java线程Java线程Java线程Java线程Java线程Java线程Java线程
主要讲述java线程volatile关键字
Java多线程与线程安全实践-基于Http协议的断点续传 Java多线程与线程安全实践-基于Http协议的断点续传 Java多线程与线程安全实践-基于Http协议的断点续传 Java多线程与线程安全实践-基于Http协议的断点续传 Java多...
JAVA语言实现:编写10个线程,第一个线程从1加到10,第二个线程从11加到20...第十个线程从91加到100,最后再把十个线程结果相加
java 线程安全的几个测试小例子,充分的理解JMM中的线程内存模型
Java线程Java线程Java线程Java线程Java线程Java线程
JAVA多线程与线程安全实践-基于Http协议的断点续传 JAVA多线程与线程安全实践-基于Http协议的断点续传 JAVA多线程与线程安全实践-基于Http协议的断点续传 JAVA多线程与线程安全实践-基于Http协议的断点续传 JAVA多...