zoukankan      html  css  js  c++  java
  • Java多线程设计模式(5)

    ===============Thread-Specific Storage Pattern============================

    比较复杂,转一篇前辈的。http://www.blogjava.net/jesson2005/articles/111204.html

    无论如何,要编写一个多执行绪安全(thread-safe)的程式总是困难的,为了使用的共用资源,您必须小心的对共用资源进行同步,同步带来一定的效能延迟,而另一方面,在处理同步的时候,又要注意物件的锁定与释放,避免产生死结,种种因素都使得编写多执行绪程式变得困难。
    Thread-Specific Storage模式尝试从另一个角度来解释多执行绪共用资源的问题,其思考点很简单,即然共用资源这麽困难,那麽就乾脆不要共用,何不为每个执行绪创造一个资源的复本,将每一个执行绪存取资料的行为加以隔离,其实现的方法,就是给予每一个执行绪一个特定空间来保管该执行绪所独享的资源,也因此而称之为 Thread- Specific Storage模式。
    在Java中可以使用java.lang.ThreadLocal来实现这个模式,这个类别是从1.2之后开始提供,不过先来看看,如何自行实现一个简单的ThreadLocal类别:
    ThreadLocal.java
    import java.util.*;
    public class ThreadLocal {
        private Map storage =
                    Collections.synchronizedMap(new HashMap());
        public Object get() {
            Thread current = Thread.currentThread();
            Object o = storage.get(current);
            if(o == null && !storage.containsKey(current)) {
                o = initialValue();
                storage.put(current, o);
            }
            return o;
        }
        public void set(Object o) {
            storage.put(Thread.currentThread(), o);
        }
        public Object initialValue() {
            return null;
        }
    }
    可以看到程式中使用执行绪本身作为key值,并将所获得的资源放在Map物件中,如果第一次使用get(),也配置一个空间给执行绪,而 initialValue()可以用来设定什麽样的初值要先储存在这个空间中,在这边先简单的设定为null。
    现在假设有一个原先在单执行绪环境下的资源SomeResource,现在考虑要该其在多执行绪环境下使用,若不想考虑复杂的执行绪共用互斥问题,此时可以使用ThreadLocal类别来使用SomeResource,例如:
    Resource.java
    public class Resource {
        private static final ThreadLocal threadLocal =
                                            new ThreadLocal();
        public static SomeResource getResource() {
            SomeResource resource =
                            (SomeResource) threadLocal.get();
            if(resource == null) {
                resource = new SomeResource();
                threadLocal.set(resource);
            }
            return resource;
        }
    }
    上面所实作的ThreadLocal类别只是一个简单的示范,您可以使用java.lang.ThreadLocal来实现Thread- Specific Storage模式,以获得更好的效能,在这边简单的示范一个Log程式,它可以记录每个执行绪的活动,所使用的是 java.util.logging中的类别:
    SimpleThreadLogger.java
    import java.io.*;
    import java.util.logging.*;                           
    public class SimpleThreadLogger {
        private static final ThreadLocal threadLocal =
                                             new ThreadLocal();
        public static void log(String msg) {
            getThreadLogger().log(Level.INFO, msg);
        }
        private static Logger getThreadLogger() {
            Logger logger = (Logger) threadLocal.get();
            if(logger == null) {
                try {
                    logger = Logger.getLogger(
                               Thread.currentThread().getName());
                    // Logger 预设是在主控台输出
                    // 我们加入一个档案输出的Handler
                    // 它会输出XML的记录文件
                    logger.addHandler(
                        new FileHandler(
                               Thread.currentThread().getName()
                               + ".log"));
                }
                catch(IOException e) {}
                threadLocal.set(logger);
            }
            return logger;
        }
    }
    可以使用下面这个程式来测试:
    LoggerTest.java
    public class LoggerTest {
        public static void main(String[] args) {
            new TestThread("thread1").start();
            new TestThread("thread2").start();
            new TestThread("thread3").start();
        }
    }
    class TestThread extends Thread {
        public TestThread(String name) {
            super(name);
        }
        public void run() {
            for(int i = 0; i < 10; i++) {
                SimpleThreadLogger.log(getName() +
                                         ": message " + i);
                try {
                    Thread.sleep(1000);
                }
                catch(Exception e) {
                    SimpleThreadLogger.log(e.toString());
                }
            }
        }
    }
    执行LoggerTest可以在主控台上看到输出,并可以在同一目录下找到三个log档,分别记录了三个执行绪的活动,透过 ThreadLocal,不用撰写复杂的执行绪共用互斥逻辑。
    Thread-Specific Storage模式的意义之一,就是「有时不共用是好的」,如果共用会产生危险,那就不要共用,当然,这种方式所牺牲掉的就是空间,您必须为每一个执行绪保留它们独立的空间,这是一种以空间换取时间与安全性的方法。

  • 相关阅读:
    Java API之时间、异常和集合
    JAVA API 之包装类、数学类和 Calendar 类
    regular expression ---正则表达式 --- REGEX 的一些补充
    正则表达式
    JavaScript 的一些应用场景分析
    JavaScript 简介
    ERROR internal error: process exited while connecting to monitor
    常用服务默认端口号
    shell笔记
    php登录注册
  • 原文地址:https://www.cnblogs.com/gaojing/p/1755653.html
Copyright © 2011-2022 走看看