`
manecocomph
  • 浏览: 3618 次
  • 性别: Icon_minigender_1
  • 来自: 上海
最近访客 更多访客>>
文章分类
社区版块
存档分类
最新评论

2011-2-17 不安全的多线程

阅读更多
在我们的代码的里面经常有这样的例子,为了格式化日期(如:2011-02-17), 就需要一个SimpleDateFormat类,同时,为了让整个系统共享这个格式化类,我们把这个格式化类写到一个公共的Util类里面,代码如下:
Util 类:
package com.maneco.art;

import java.text.SimpleDateFormat;

public class Util {
	public static final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
	
}

Util类的使用者:
package com.maneco.art;

import java.text.ParseException;

public class MultiThread implements Runnable {

	public static void main(String[] args) {
		new Thread(new MultiThread()).start();
		new Thread(new MultiThread()).start();
		new Thread(new MultiThread()).start();
		new Thread(new MultiThread()).start();
	}

	@Override
	public void run() {
		try {
			for (int i = 0; i < 10000; i++) {
				System.out.print(Util.sdf.parse("2000-01-05"));
			}
		} catch (ParseException e) {
			e.printStackTrace();
		}
	}
}

如上面的代码,就会产生下面的异常:
Exception in thread "Thread-0" java.lang.NumberFormatException: For input string: ""
	at java.lang.NumberFormatException.forInputString(Unknown Source)
	at java.lang.Long.parseLong(Unknown Source)
	at java.lang.Long.parseLong(Unknown Source)
	at java.text.DigitList.getLong(Unknown Source)
	at java.text.DecimalFormat.parse(Unknown Source)
	at java.text.SimpleDateFormat.subParse(Unknown Source)
	at java.text.SimpleDateFormat.parse(Unknown Source)
	at java.text.DateFormat.parse(Unknown Source)
	at com.maneco.art.MultiThread.run(MultiThread.java:18)
	at java.lang.Thread.run(Unknown Source)

原因在于:
如果是单线程,使用这个Util类是没有问题的;
如果是多线程的话,就会产生并发访问同一个实例化的SimpleDateFormat类。
JDK API中声明DateFormat类和SimpleDateFormat类都不是线程同步的,推荐对于每个线程创建一个实例。如果多线程访问的话,自己实现多线程同步;
1: 最简单的方法是在每次使用的时候,new一个新的DateFormat;效率稍许损失,不能达到系统共享同一个格式化类。最简单的编程模型。推荐。
2: 增加线程同步访问: 但是多线程的效率将损失,并且容易导致死锁。
private static final SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
	public static synchronized Date formatStr(String str) throws ParseException {
		return Util.df.parse(str);
	}

下面这种线程同步是没有意义的,因为仅仅拿到reference时是线程同步的,而不是使用时同步的。
private static final SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
	public static synchronized DateFormat getDateFomrater() {
		return Util.df;
	}

3: 如果对性能要求严格,可以封装一个类,在同步的代码里面对于每个线程根据线程Id去返回对应的实例类,
   效率稍微损失,不会导致死锁,系统的格式化聚集在一个访问点:
private static final Map<Long, DateFormat> DateFormaterMap = new HashMap<Long, DateFormat>();
	// return date formater by thread Id
	public static DateFormat getDateFormaterByThread() {
		Long tId = Thread.currentThread().getId();
		
		if (Util.DateFormaterMap.containsKey(tId)) {
			return Util.DateFormaterMap.get(tId);
		} else {
			// another strategy: use SimpleDateFormat's clone method with a default one
			SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
			Util.DateFormaterMap.put(tId, sdf);
			return sdf;
		}
	}

建议在写单元测试的时候,增加一项多线程测试。
分享到:
评论

相关推荐

    Java SE Tutorials (Last Updated 2011-03-17)

    7. **多线程**:Java提供了内置的对多线程的支持,包括Thread类和Runnable接口,以及同步机制如synchronized关键字、wait()、notify()和notifyAll()方法。 8. **网络编程**:理解Socket编程,包括TCP和UDP通信,...

    2011-9-17阿里云笔试题目

    **详细解释**:线程同步单例设计模式是指在一个多线程环境中,确保类的实例唯一并且安全地被创建。常见的实现方式包括懒汉式、饿汉式、双重检查锁定等。其中,双重检查锁定方式在保证线程安全的同时,也能提高性能:...

    C++2011标准_ISO_IEC-14882-2011_ISOIEC_ISOIEC148822011_ISO_IEC14882

    9. **多线程支持(Multi-threading)**:C++2011标准库提供了`&lt;thread&gt;`头文件,支持并发编程,包括`std::thread`,同步原语如`std::mutex`,`std::condition_variable`等。 10. **并行算法(Parallel Algorithms)...

    鼎普科技2011-2012招聘C++LINUX题

    4. **网络编程**:在Linux环境下,TCP/IP协议栈的使用,套接字编程,以及并发服务的实现,如多线程、异步IO或者epoll模型。 5. **调试与优化**:如何使用gdb进行程序调试,性能分析工具如gprof、valgrind的使用,...

    (0积分)C语言标准(c89,c99,c11,c17,c2x)

    - **多线程支持**:通过 `&lt;threads.h&gt;` 头文件提供。 - **原子操作**:通过 `&lt;stdatomic.h&gt;` 头文件实现线程间的同步。 - **可选的尾部注释**:允许在函数声明和定义的末尾添加注释。 - **静态断言**:在编译时...

    nServer-v2.1023[FTP + MYSQL + HTTP + PHP(FCGI)]

    支持php54/3/2版本切换或多版本同时运行,支持为独立站点配置独立php进程,保证站点安全。 支持Zend/eAccelerator/Mencached/XCache等扩展服务。 支持FileZilla提供的ftp服务。 - - - - - - - - - - - - - -组件...

    2005-2011年全新各大公司j2ee面试题汇总大全

    ### Java基础知识点解析 #### 1. 多个类在一个.java文件中 - 在一个`.java`源文件中...以上内容涵盖了从Java基础知识到进阶多线程和异常处理等多个方面的知识点,对于理解Java编程的核心概念和技术细节非常有帮助。

    jdk17win32.zip

    此外,JDK7还增强了并发编程的支持,例如Fork/Join框架和并行流API,这使得开发者能够更容易地编写高性能的多线程应用。 JDK17则是Java的长期支持(LTS)版本,意味着它将得到更长时间的安全更新和技术支持。JDK17...

    jdk-7u80-windows-x86.exe文件.zip

    - **多线程并发API增强**:Java 7引入了Fork/Join框架,这是一种基于工作窃取算法的并行编程模型,可以有效地利用多核处理器资源,提高程序执行效率。 - **动态语言支持**:JDK 7通过JSR 292( invokedynamic ...

    360安全卫士诊断报告

    2. **浏览器版本落后**: Internet Explorer 6版本过旧,不支持现代网络技术,并且存在许多已知的安全问题。 3. **未知的注册表设置和工具栏**: 可能是由第三方软件安装造成的,需要进一步检查确认是否为恶意行为。 4...

    Java面试宝典2011版

    - `StringBuffer`提供了线程安全的字符串操作,适合在多线程环境中使用。 **25. 数组转换为字符串数组** - 可以使用`split()`方法将逗号分隔的字符串转换为字符串数组。 - 示例:`String[] array = "a,b,c,d".split...

    官网版jdk1.7.0_17.rar

    - 安全性方面,Java 7进行了多项安全增强,包括改进的证书管理和更强的加密算法。 5. **开发者工具**: - `javac`:Java源代码编译器,将.java文件编译成.class字节码文件。 - `jar`:打包工具,可以创建、更新...

    Master-Class-C++11.pdf

    - 、和&lt;mutex&gt;:分别支持多线程、异步编程和线程同步。 2. 关键概念: - C++11概念:提供一种模板编程的方法,用于参数化类型,从而使得模板更具有通用性。 - 委托构造函数:允许构造函数调用另一个构造函数来...

    2011Android技术面试

    ### 2011 Android技术面试知识点详解 #### 1. Android的四大组件及其作用 - **Activity**:这是Android程序与用户交互的主要界面。它负责显示UI元素,并且能够响应用户的操作。每个Activity都有自己的生命周期,即...

    2011最新Java程序员面试笔试宝典

    - 实现多线程的方法主要有两种:继承`Thread`类和实现`Runnable`接口。 - 实现同步的方法包括使用`synchronized`关键字、`ReentrantLock`等。 #### 51. 启动一个线程是用run()还是start()? 启动一个线程应该使用`...

    vc++ 开发实例源码包

    实现了自绘控件,云端控制主要在CnComm类多线程串口通讯库, camerads-DirectShow使用示例 演示了摄像头的使用 CatListBoxDemo ListBox控件与其它控件阙套使用方法 CCAMS系统是一种用于局域网下的CS模式的软件...

Global site tag (gtag.js) - Google Analytics