java hashtable 到底是不是线程安全的?

问题描述

如题,看网上很多人都说这个类是线程安全的,但我看了jdk1.6 的源码,并没有发现这类的线程安全机制,这个类到底是不是安全的,如果是的话,安全机制如何实现的? 问题补充:/* * Copyright 2001-2004 The Apache Software Foundation. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. *//* * $Id: Hashtable.java,v 1.4 2004/02/16 22:55:54 minchau Exp $ */package com.sun.org.apache.xalan.internal.xsltc.runtime;import java.util.Enumeration;/** * IMPORTANT NOTE: * This code was taken from Sun's Java1.1 JDK java.util.HashTable.java * All "synchronized" keywords and some methods we do not need have been * all been removed. *//** * Object that wraps entries in the hash-table * @author Morten Jorgensen */class HashtableEntry { int hash; Object key; Object value; HashtableEntry next; protected Object clone() {HashtableEntry entry = new HashtableEntry();entry.hash = hash;entry.key = key;entry.value = value;entry.next = (next != null) ? (HashtableEntry)next.clone() : null;return entry; }}/** * The main hash-table implementation */public class Hashtable { private transient HashtableEntry table[]; // hash-table entries private transient int count; // number of entries private int threshold; // current size of hash-tabke private float loadFactor; // load factor /** * Constructs a new, empty hashtable with the specified initial * capacity and the specified load factor. */ public Hashtable(int initialCapacity, float loadFactor) {if (initialCapacity <= 0) initialCapacity = 11;if (loadFactor <= 0.0) loadFactor = 0.75f;this.loadFactor = loadFactor;table = new HashtableEntry[initialCapacity];threshold = (int)(initialCapacity * loadFactor); } /** * Constructs a new, empty hashtable with the specified initial capacity * and default load factor. */ public Hashtable(int initialCapacity) {this(initialCapacity, 0.75f); } /** * Constructs a new, empty hashtable with a default capacity and load * factor. */ public Hashtable() {this(101, 0.75f); } /** * Returns the number of keys in this hashtable. */ public int size() {return count; } /** * Tests if this hashtable maps no keys to values. */ public boolean isEmpty() {return count == 0; } /** * Returns an enumeration of the keys in this hashtable. */ public Enumeration keys() {return new HashtableEnumerator(table, true); } /** * Returns an enumeration of the values in this hashtable. * Use the Enumeration methods on the returned object to fetch the elements * sequentially. */ public Enumeration elements() {return new HashtableEnumerator(table, false); } /** * Tests if some key maps into the specified value in this hashtable. * This operation is more expensive than the <code>containsKey</code> * method. */ public boolean contains(Object value) {if (value == null) throw new NullPointerException();int i;HashtableEntry e;HashtableEntry tab[] = table;for (i = tab.length ; i-- > 0 ;) { for (e = tab[i] ; e != null ; e = e.next) {if (e.value.equals(value)) { return true;} }}return false; } /** * Tests if the specified object is a key in this hashtable. */ public boolean containsKey(Object key) {HashtableEntry e;HashtableEntry tab[] = table;int hash = key.hashCode();int index = (hash & 0x7FFFFFFF) % tab.length;for (e = tab[index] ; e != null ; e = e.next) if ((e.hash == hash) && e.key.equals(key))return true;return false; } /** * Returns the value to which the specified key is mapped in this hashtable. */ public Object get(Object key) {HashtableEntry e;HashtableEntry tab[] = table;int hash = key.hashCode();int index = (hash & 0x7FFFFFFF) % tab.length;for (e = tab[index] ; e != null ; e = e.next) if ((e.hash == hash) && e.key.equals(key)) return e.value;return null; } /** * Rehashes the contents of the hashtable into a hashtable with a * larger capacity. This method is called automatically when the * number of keys in the hashtable exceeds this hashtable's capacity * and load factor. */ protected void rehash() {HashtableEntry e, old;int i, index;int oldCapacity = table.length;HashtableEntry oldTable[] = table;int newCapacity = oldCapacity * 2 + 1;HashtableEntry newTable[] = new HashtableEntry[newCapacity];threshold = (int)(newCapacity * loadFactor);table = newTable;for (i = oldCapacity ; i-- > 0 ;) { for (old = oldTable[i] ; old != null ; ) {e = old;old = old.next;index = (e.hash & 0x7FFFFFFF) % newCapacity;e.next = newTable[index];newTable[index] = e; }} } /** * Maps the specified <code>key</code> to the specified * <code>value</code> in this hashtable. Neither the key nor the * value can be <code>null</code>. * <p> * The value can be retrieved by calling the <code>get</code> method * with a key that is equal to the original key. */ public Object put(Object key, Object value) {// Make sure the value is not nullif (value == null) throw new NullPointerException();// Makes sure the key is not already in the hashtable.HashtableEntry e;HashtableEntry tab[] = table;int hash = key.hashCode();int index = (hash & 0x7FFFFFFF) % tab.length;for (e = tab[index] ; e != null ; e = e.next) { if ((e.hash == hash) && e.key.equals(key)) {Object old = e.value;e.value = value;return old; }}// Rehash the table if the threshold is exceededif (count >= threshold) { rehash(); return put(key, value);} // Creates the new entry.e = new HashtableEntry();e.hash = hash;e.key = key;e.value = value;e.next = tab[index];tab[index] = e;count++;return null; } /** * Removes the key (and its corresponding value) from this * hashtable. This method does nothing if the key is not in the hashtable. */ public Object remove(Object key) {HashtableEntry e, prev;HashtableEntry tab[] = table;int hash = key.hashCode();int index = (hash & 0x7FFFFFFF) % tab.length;for (e = tab[index], prev = null ; e != null ; prev = e, e = e.next) { if ((e.hash == hash) && e.key.equals(key)) {if (prev != null) prev.next = e.next;else tab[index] = e.next;count--;return e.value; }}return null; } /** * Clears this hashtable so that it contains no keys. */ public void clear() {HashtableEntry tab[] = table;for (int index = tab.length; --index >= 0; ) tab[index] = null;count = 0; } /** * Returns a rather long string representation of this hashtable. * Handy for debugging - leave it here!!! */ public String toString() {int i;int max = size() - 1;StringBuffer buf = new StringBuffer();Enumeration k = keys();Enumeration e = elements();buf.append("{");for (i = 0; i <= max; i++) { String s1 = k.nextElement().toString(); String s2 = e.nextElement().toString(); buf.append(s1 + "=" + s2); if (i < max) buf.append(", ");}buf.append("}");return buf.toString(); } /** * A hashtable enumerator class. This class should remain opaque * to the client. It will use the Enumeration interface. */ class HashtableEnumerator implements Enumeration {boolean keys;int index;HashtableEntry table[];HashtableEntry entry;HashtableEnumerator(HashtableEntry table[], boolean keys) { this.table = table; this.keys = keys; this.index = table.length;}public boolean hasMoreElements() { if (entry != null) {return true; } while (index-- > 0) {if ((entry = table[index]) != null) { return true;} } return false;}public Object nextElement() { if (entry == null) {while ((index-- > 0) && ((entry = table[index]) == null)); } if (entry != null) {HashtableEntry e = entry;entry = e.next;return keys ? e.key : e.value; } return null;} }}

解决方案

public synchronized int size() { public synchronized boolean isEmpty() { public synchronized boolean contains(Object value) { public synchronized Enumeration<K> keys() { public synchronized V get(Object key) { public synchronized V put(K key, V value) { public synchronized V remove(Object key) { public synchronized void putAll(Map<? extends K, ? extends V> t) { public synchronized void clear() { public synchronized Object clone() { public synchronized String toString() { private transient volatile Set<K> keySet = null; private transient volatile Set<Map.Entry<K,V>> entrySet = null; private transient volatile Collection<V> values = null; public Set<Map.Entry<K,V>> entrySet() {if (entrySet==null) entrySet = Collections.synchronizedSet(new EntrySet(), this);return entrySet; }你再自己去查一下 synchronized,volatile,Collections.synchronizedSet 的用法吧。
解决方案二:
你确定hashtable包在com.sun.org.apache.xalan.internal.xsltc.runtime;下面吗

时间: 2024-07-31 13:12:54

java hashtable 到底是不是线程安全的?的相关文章

java内存模型与线程(转) good

java内存模型与线程 参考 http://baike.baidu.com/view/8657411.htm  http://developer.51cto.com/art/201309/410971_all.htm http://www.cnblogs.com/skywang12345/p/3447546.html 计算机的CPU计算能力超强,其计算速度与 内存等存储 和通讯子系统的速度相比快了几个数量级, 数据加载到内存中后,cpu处理器运算处理时,大部分时间花在等待获取去获取磁盘IO.网络

Java基础-创建Java程序中的线程池

程序|创建 线程是Java的一大特性,它可以是给定的指令序列.给定的方法中定义的变量或者一些共享数据(类一级的变量).在Java中每个线程有自己的堆栈和程序计数器(PC),其中堆栈是用来跟踪线程的上下文(上下文是当线程执行到某处时,当前的局部变量的值),而程序计数器则用来跟踪当前线程正在执行的指令. 在通常情况下,一个线程不能访问另外一个线程的堆栈变量,而且这个线程必须处于如下状态之一: 1.排队状态(Ready),在用户创建了一个线程以后,这个线程不会立即运行.当线程中的方法start()被调

Java 6中的线程优化真的有效么?

介绍 - Java 6中的线程优化 Sun.IBM.BEA和其他公司在各自实现的Java 6虚拟机上都花费了大量的精力 优化锁的管理和同步.诸如偏向锁(biased locking).锁粗化(lock coarsening).由逸出(escape)分析产生的锁省略.自适应自旋锁(adaptive spinning)这些特性,都是通过在应用程序线程之间更高效地共享数据,从而提 高并发效率.尽管这些特性都是成熟且有趣的,但是问题在于:它们的承诺真的 能实现么?在这篇由两部分组成的文章里,我将逐一探究

一个Java对象到底占多大内存?(转)

最近在读<深入理解Java虚拟机>,对Java对象的内存布局有了进一步的认识,于是脑子里自然而然就有一个很普通的问题,就是一个Java对象到底占用多大内存? 在网上搜到了一篇博客讲的非常好:http://yueyemaitian.iteye.com/blog/2033046,里面提供的这个类也非常实用: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35

java中简单的线程问题

问题描述 java中简单的线程问题 我只创建了一个对象,为何运行的时候会有两个第五张票出现?即便是把上面的tickets变量加上static也是同样的结果 解决方案 加不加static与是否会发生多线程冲突无关,你需要在执行代码处加个锁防止多个线程同时调用一个对象 解决方案二: 源代码发我一下,多线程就是指多个对象对某个RUN方法多次调用. 解决方案三: 线程同步问题吧... 最好贴个代码出来. 解决方案四: 如果不想修改代码,也找不到错误,那么就在要执行逻辑代码之前去下重呗,虽然这样不合理.

多线程问题-新手求助关于Java多线程中启动线程问题

问题描述 新手求助关于Java多线程中启动线程问题 public class Example15_1 { /** * @param args */public static void main(String[] args) { // TODO Auto-generated method stub SpeakHello speakHello; SpeakNinhao speakNinhao; speakHello = new SpeakHello(); speakNinhao= new Speak

java中panel实现线程接口以后,要调用repaint函数时,不进run函数

问题描述 java中panel实现线程接口以后,要调用repaint函数时,不进run函数 具体情况是 mypanel类实现了线程接口,在run函数中定义了sleep(100)后调用repaint函数,做一个小坦克游戏,在repaint之前要判断是否击中坦克,击中后要显示三张图片来体现爆炸效果,可是经过调试发现,每次第一次击中的时候,都是直接好多次repaint,没有休眠,后来发现根本就没有进mypanel的run()方法,好像有另一个其他线程再调用paint.这是怎么回事?感谢大家了 pack

继承-java中到底为什么要用到抽象类?

问题描述 java中到底为什么要用到抽象类? 比如有个类A,把它设置成abstract是为了不让它实例化,只能表示一个抽象的或者不具体的无法实例化的概念,但是就算不在这个A的前面加abstract照样可以实现很多类的继承,那我真的不太理解设置抽象类的意义到底在哪里,请各位不吝赐教! 解决方案 抽象类定义一些有一定关系的类的共同行为,比如一个几何图形类,几何图形包括多种图形,如,正方形,圆形,矩形,三角形等,而每种图形用有各自的面积周长计算公式,所以可以在几何图形类里抽象这些公共方法,而不提供真正

多线程-JAVA中如何在一个线程里面停掉另一个线程

问题描述 JAVA中如何在一个线程里面停掉另一个线程 JAVA中如何在一个线程里面停掉另一个线程,是在一个线程里面哦 PS:新人第一次问问题,希望大神求教 解决方案 定义一个共享变量在run方法里面 while(start){ } 解决方案二: 所以说,这个问题的答案是:不可以! 虽然的确有那么个方法可以摧毁别人的线程,但很早很早就已经过期了,如果没记错的话我之前也这么玩,而结果是这个过期的方法根本没有作用-- 虽然说办法不是没有,那就是通过改变变量值,它知道自己该死了,就退出循环,走向结束.