JAVA 多线程应用总结 一

JAVA 多线程应用总结<一>

一、ThreadLocal 线程本地变量,ThreadLocal为变量在每个线程中都创建了一个副本,那么每个线程可以访问自己内部的副本变量。是一个时间->空间的转换(内存的占用会比不使用ThreadLocal要大).

  • 每个线程Thread内部有一个ThreadLocal.ThreadLocalMap类型的成员变量threadLocals,这个threadLocals就是用来存储实际的变量副本的,键值为当前ThreadLocal变量,value为变量副本(即T类型的变量)

public void set(T value) {
    Thread t = Thread.currentThread();
    ThreadLocalMap map = getMap(t);
    if (map != null)
        map.set(this, value);
    else
        createMap(t, value);
}

void createMap(Thread t, T firstValue) {
    t.threadLocals = new ThreadLocalMap(this, firstValue);
}
  • 在使用get()前需要先set()否则空指针。除非在初始化时进行
/**
 * 控制各线程记录开关
 */
public final static ThreadLocal<Boolean> LOCAL =new ThreadLocal<Boolean>(){
    @Override
    protected Boolean initialValue() {
        return true;
    }
};

/**
 * 控制各线程记录开关
 */
public final static ThreadLocal<Boolean> LOCAL =ThreadLocal.withInitial(()->true);
  • 在Thread中使用完ThreadLocal对象后,一定要记得调用ThreadLocal的remove方法,进行手动清除。
MonitorConstant.LOCAL.remove();

二、ThreadPoolExecutor 线程池

/**
 * workQueue(任务队列) : 用于保存等待执行的任务的阻塞队列
 * 1)   ArrayBlockingQueue:是一个基于数组结构的有界阻塞队列,按FIFO原则进行排序
 * 2)   LinkedBlockingQueue:一个基于链表结构的阻塞队列,吞吐量高于ArrayBlockingQueue
 * 静态工厂方法Excutors.newFixedThreadPool()使用了这个队列
 * 3)SynchronousQueue: 一个不存储元素的阻塞队列。每个插入操作必须等到另一个线程调用移除操作,否则插入操作一直处于阻塞状态,吞吐量高于LinkedBlockingQueue
 * 静态工厂方法Excutors.newCachedThreadPool()使用了这个队列
 * 4)PriorityBlockingQueue:一个具有优先级的无限阻塞队列。
 * 
 * handler : 线程池对拒绝任务的处理策略。
 * 1) ThreadPoolExecutor.AbortPolicy 丢弃任务,并抛出 RejectedExecutionException 异常。
 * 2) ThreadPoolExecutor.CallerRunsPolicy:该任务被线程池拒绝,由调用 execute方法的线程执行该任务。
 * 3) ThreadPoolExecutor.DiscardOldestPolicy : 抛弃队列最前面的任务,然后重新尝试执行任务。
 * 4) ThreadPoolExecutor.DiscardPolicy,丢弃任务,不过也不抛出异常。
 */
private static ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(CORE_POOL_SIZE, MAX_POOL_SIZE, KEEP_ALIVE_TIME, TimeUnit.SECONDS, new LinkedBlockingQueue<>(), new NotifierThreadFactory(), new ThreadPoolExecutor.AbortPolicy());

三、Semaphore(计数信号量)  每个acquire方法阻塞,直到有一个许可证可以获得然后拿走一个许可证;每个release方法增加一个许可证,这可能会释放一个阻塞的acquire方法  --------->   Semaphore经常用于限制获取某种资源的线程数量。

private static final Semaphore SEMAPHORE = new Semaphore(POOL_SIZE);

public static void startJob(Callback event) {
    try {
        SEMAPHORE.acquire();
    } catch ( InterruptedException ignored ) {}
    threadPoolExecutor.execute(() -> {
        int     retry = 0;
        boolean loop;
        do {
            try {
                if ( event.call() ) {
                    loop = false;
                } else {
                    throw new Exception(" event 's call() return false ");
                }
            } catch ( Exception e ) {
                loop = true;
                if ( retry >= TIME_BLOCK.length ) {
                    logger.error(" a Notifier died. ", e);
                    loop = false;
                } else {
                    try {
                        Thread.sleep(TIME_BLOCK[retry++]);
                    } catch ( InterruptedException ignored ) {}
                }
            }
        } while ( loop );
        SEMAPHORE.release();
    });
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值