简体   繁体   English

为什么Properties.list在打印前复制表?

[英]Why does Properties.list copy table before printing?

Here's the implementation of Properties.list from JDK: 这是JDK的Properties.list的实现:

public void list(PrintWriter out) {
    out.println("-- listing properties --");
    Hashtable<String,Object> h = new Hashtable<>();
    enumerate(h);
    for (Enumeration<String> e = h.keys() ; e.hasMoreElements() ;) {
        String key = e.nextElement();
        String val = (String)h.get(key);
        if (val.length() > 40) {
            val = val.substring(0, 37) + "...";
        }
        out.println(key + "=" + val);
    }
}

What are the lines 有什么路线

Hashtable<String,Object> h = new Hashtable<>();
enumerate(h);

for? 对于? Couldn't it just use original table instead of making a copy and reading data from it? 它不能只使用原始表而不是复制和从中读取数据吗?

这是允许线程安全迭代的常用习惯用法(即,如果另一个线程在循环期间修改哈希表,则不会出现ConcurrentModificationException )。

The list() method is not synchronized. list()方法未同步。
So any invocation (even those synchronized) on the Properties instance during list() invocation may break the state of the object and result to an exception or a broken logic. 因此,在list()调用期间对Properties实例的任何调用(甚至那些已同步)都可能会破坏对象的状态并导致异常或逻辑损坏。

Suppose that instead using an intermediate Properties instance, we iterate directly on the Properties instance it would be no thread safe 假设使用中间的Properties实例,我们直接在Properties实例上迭代它将不是线程安全的

Suppose that we have two threads : Thread A that calls this list() method and Thread B that calls remove() on a same Properties instance. 假设我们有两个线程:调用此list()方法的线程A和调用同一Properties实例上的remove()线程B.

This code in the list() method has multiple race conditions. list()方法中的此代码具有多个竞争条件。

To illustrate, we could use this snippet of the list() method : 为了说明,我们可以使用list()方法的这个片段:

   String key = e.nextElement();
   String val = (String)h.get(key);
   if (val.length() > 40) {

Suppose the thread A is paused after this instruction : 假设在此指令后线程A暂停:

 String key = e.nextElement();  

The thread B is resumed and invokes instance.remove() with as parameter the object associated to the key retrieved by the Thread A 线程B被恢复,并使用与线程A检索的密钥相关联的对象作为参数调用instance.remove()

Then when the thread A is resumed it goes to the next instruction : 然后当线程A恢复时,它转到下一条指令:

 String val = (String)h.get(key);

The value doesn't exist any longer. 该值不再存在。

The next instruction raises an exception as val is null : val为null ,下一条指令引发异常:

    if (val.length() > 40) {

This is an optimization for multithreaded applications. 这是多线程应用程序的优化。

A Properties object is meant to be thread safe, so they had to either make the method synchronized (which is a bad idea since writing to a PrintStream can block for a long time, holding the lock), or they can just quickly copy the contents to a new hashtable within a synchronized block ( enumerate is synchronized), and then printing the items of the copy, without holding a lock. 一个Properties对象意味着线程安全,所以他们必须使方法同步(这是一个坏主意,因为写入PrintStream可以长时间阻塞,持有锁),或者他们可以快速复制内容到同步块中的新哈希表( enumerate已同步),然后打印副本的项目,而不保持锁定。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM