添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
针对静态方法有以下一些前提
  • 静态方法和实例方法的区别是静态方法只能引用静态变量,静态方法通过类名来调用,实例方法通过对象实例来调用
  • 每个线程都有自己的线程栈,栈与线程同时创建,每一个虚拟机线程都有自己的程序计数器PC,在任何时刻,一个虚拟机线程只会执行一个方法的代码,这个方法称为该线程的当前方法,如果这个方法不是native的,程序计数器就保存虚拟机正在执行的字节码指令的地址。
  • 线程调用方法的时候会创建栈帧,用于保存局部变量表和操作数栈以及指向该类常量池的引用
  • 静态方法虽然是同一个方法,但是不同线程在调用,程序计数器的值是不一样的,操作这两个线程不会相互影响(假设不存在访问共享变量的情况)

在设计工具类时,这要没有共享的变量,静态工具类方法不需要加锁。在使用单例模式做工具类,这个时候静态方法就需要加锁,因为所有的线程虽然都是有自己的方法栈,但是在方法栈中操作的是同一个对象的实体(所以需要加锁,加锁的代价是所有的线程需要等待锁的释放才能使用该对象的引用)在使用多例模式做工具类时,这个时候也是不需要加锁,因为所有的线程都有自己的方法栈,但是方法栈帧中创建了独立的对象引用,每个线程都是在操作各自方法栈帧中的局部对象引用,所以这时候不要同步。

那么问题来了,如果有共享变量的时候应该怎么办呢?一下是一些建议

由于web天生并发性,导致我们的一般java工具类会在这样的环境下出现问题。

其实问题的根源就是我们的工具类不是线程安全的。

有一个生成md5的工具类:

public class MD5 {  
    private static long[] state = new long[4];  
    private static long[] count = new long[2];  
    private static byte[] buffer = new byte[64];  
    private static byte[] digest = new byte[16];  
    private String digestHexStr="";  
    public static MD5() {  
    //计算MD5  
    public static String getMD5ofStr(String inbuf) {  

变量state, count ,buffer ,digest 算法中用到的核心数据,digestHexStr存放计算的结果。在多线程并发访问的情况下,这些变量是会被“共享”的,所以会导致计算结果不准确甚至出现异常。

有三种比较简单的方法可以解决:

getMD5ofStr方法变成非static的普通方法,这样每次调用这个方法都必须new一个新的MD5对象。

getMD5ofStr方法变成同步方法(同步代码块,显示锁,synchronized method都可以)。

将被“共享”的变量放到方法getMD5ofStr里面,不设置成员变量。

考虑到现在系统有些地方已经开始使用这个工具类了,不便改动结构,先采用第二种快速修复bug,然后腾出时间用第三种发放重构。

工具类能否设计成单例?如果能最好。单例能减少创建类和分配内存的开销,减少垃圾回收次数。

工具类能否设计成不变类?如果能最好,不变类天生线程安全!

在并发环境下,工具类能不能不用同步?不管怎么说,同步都是要有一些开销的。

这样会好一些:

public final class MD5 {  
    private MD5(){}  
    //计算MD5  
    public static String getMD5ofStr(String inbuf) {  
        long[] state = new long[4];  
        long[] count = new long[2];  
        byte[] buffer = new byte[64];  
        byte[] digest = new byte[16];  
        String digestHexStr="";  
        ........  

原文链接:http://www.cnblogs.com/LvLoveYuForever/p/6077148.html

http://blog.csdn.net/baohuan_love/article/details/14209317

public static SimpleDateFormat sdfTest = new SimpleDateFormat("yyyy年MM月dd日"); public static Date selectDate(String stageDuring) { try { System.out.println(Thread.currentThread().getId()+"==睡眠前=="+stageDuring); Thread.sleep(10*10
public void handleJSON(JSONArray data, int threadNum){ int length = data.size(); int tl = length % threadNum == 0 ? length / threadNum : (length / threadNum + 1);
一般来说,工具类都是静态方法,只要静态方法内不引用可更改状态的静态字段就是线程安全的。因为每次调用都会分配新的栈空间。 但,若传入的是引用型变量,而且如果同一个对象可能同时传入给2个可更改其状态的静态方法,就会存在线程安全问题。 根本还是要清楚,静态方法内是否含有状态可更改的共享资源。 public class MyThread implements Runnable ...
RT-Thread 实时操作系统核心是一个高效的硬实时核心,它具备非常优异的实时性、稳定性、可剪裁性,当进行最小配置时,内核体积可以到 3k ROM 占用、 1k RAM 占用。 RT-Thread 中的“线程”一般由三部分组成:线程代码(函数)、 线程控制块、 线程堆栈。 /* 指向线程控制块的指针*/ static structrt_thread led_threa...
[b]1.静态方法[/b] 无论是静态方法还是实例方法,在内存中都只有一份代码,也就是只占用一份内存空间 方法属于一个程序块,只有当别人调用它时才会调到内存里面去执行,也就是说当前有多少个线程在执行就有多少组方法块里的局部变量 [b]2.静态变量[/b] 只存在一份,多个线程公用一份,一个线程修改就会影响其他线程 [b]3.结论[/b] 静态方法是使用得当...
静态方法和实例方法的区别是静态方法只能引用静态变量,静态方法通过名来调用,实例方法通过对象实例来调用 每个线程都有自己的线程栈,栈与线程同时创建,每一个虚拟机线程都有自己的程序计数器PC,在任何时刻,一个虚拟机线程只会执行一个方法的代码,这个方法称为该线程的当前方法,如果这个方法不是native的,程序计数器就保存虚拟机正在执行的字节码指令的地址。 线程调用方法的时候会创建栈帧...
静态初始化块里启动新线程的陷阱 一:问题的提出           我们知道静态块帮助我们完成一些的初始化的工作,那么在静态块里面启动一个线程,让它来帮助我们来完成初始化的工作会发生什么哪?死锁还是输出了让我们感觉不是我们想要的结果呐?,不妨试试看,结果是什么吧. 二:具备的知识         多线程的基础知识, 多线程的创建,启动,join()方法和匿名内部的使用等.例子比较简单的
org.springframework.web.servlet.handler.AbstractHandlerMethodMapping$MappingRegistry异常的解决方法 14322