写系统代码的时候遇到一个对象锁的问题。场景描述如下:
我有一个系统系统需要按照集群名称发送任务给执行任务的系统。这个分发任务给执行任务的系统的过程是并发的。我需要控制一下发送任务的数量,为改数量设定一个阈值。比如:一次只能发送10个任务。
在这个过程中,我需要针对集群名称(String clusterName)进行加锁。因为我会同时给很多集群发送任务,我只需要确保给每个集群分发任务的时候是加锁串行的,但是每个不同集群之间不存在资源竞争,不需要加锁。
我开始想给String clusterName加锁,但是网上文章说这样对字符串加锁非常不好。
参考:
http://www.blogjava.net/qujinlong123/archive/2007/05/31/121200.html
但是我确实需要一个关于集群名字的锁。下面有个类似的例子实现:
https://segmentfault.com/q/1010000007893810
给字符串加锁,如果该字符串执行 split() 或者 intern() 等操作时都会被锁住。
那该如何处理呢? 而且为 “hello” 加锁和 new String("hello") 加锁是不行的,它们是2个对象。虽然它们比较equals是相等的。
我采用为这个字符串(String clusterName)进行一次封装的形式进行加锁。
如下:
/** * <pre> * Copyright test.com CDC [2000-2017] * </pre> */ package com.test.tmp; import com.google.common.base.Preconditions; import com.google.common.collect.Maps; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.TimeUnit; /** * <pre> * Test.java * @author kanpiaoxue<br> * @version 1.0 * Create Time 2017年1月17日 下午7:47:40<br> * Description : TODO 类实现描述 * </pre> */ public class Test { public static final ConcurrentMap<String, ClusterLock> map = Maps.newConcurrentMap(); /** * <pre> * @param args * </pre> * * @throws Exception */ public static void main(String[] args) throws Exception { new Thread(new Runnable() { @Override public void run() { String clusterName = new String("luowenlei"); ClusterLock v = new ClusterLock(clusterName); ClusterLock tmp = map.putIfAbsent(clusterName, v); if (null == tmp) { System.out.println(Thread.currentThread() + " -- first"); tmp = v; } ClusterLock clusterNameForLock = tmp; synchronized (clusterNameForLock) { System.out.println("locked ..."); try { TimeUnit.SECONDS.sleep(10L); } catch (InterruptedException e) { } System.out.println("unlocked ..."); } } }).start(); TimeUnit.SECONDS.sleep(1L); new Thread(new Runnable() { @Override public void run() { String clusterName = new String("luowenlei"); ClusterLock v = new ClusterLock(clusterName); ClusterLock tmp = map.putIfAbsent(clusterName, v); if (null == tmp) { System.out.println(Thread.currentThread()); tmp = v; } System.out.println(Thread.currentThread() + " -- second"); ClusterLock clusterNameForLock = tmp; synchronized (clusterNameForLock) { System.out.println("locked lock1 ..."); System.out.println("unlocked lock1 ..."); } } }).start(); } } class ClusterLock { private String clusterName; /** * <pre> * @param clusterName * </pre> */ public ClusterLock(String clusterName) { super(); this.clusterName = clusterName; } /* * (non-Javadoc) * @see java.lang.Object#hashCode() */ @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((clusterName == null) ? 0 : clusterName.hashCode()); return result; } /* * (non-Javadoc) * @see java.lang.Object#equals(java.lang.Object) */ @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; ClusterLock other = (ClusterLock) obj; if (clusterName == null) { if (other.clusterName != null) return false; } else if (!clusterName.equals(other.clusterName)) return false; return true; } /* * (non-Javadoc) * @see java.lang.Object#toString() */ @Override public String toString() { return "ClusterLock [clusterName=" + clusterName + "]"; } }
正确打印的日志信息如下:
写道
Thread[Thread-0,5,main] -- first
locked ...
Thread[Thread-1,5,main] -- second
unlocked ...
locked lock1 ...
unlocked lock1 ...
locked ...
Thread[Thread-1,5,main] -- second
unlocked ...
locked lock1 ...
unlocked lock1 ...
这样就解决了为字符串加锁的弊端的问题,同时做到了为集群加锁的功能。
相关推荐
Java并发编程是Java开发中的重要领域,特别是在多核处理器和分布式系统中,高效地利用并发可以极大地提升程序的性能和响应速度。以下是对标题和描述中所提及的几个知识点的详细解释: 1. **线程与并发** - **线程*...
### Java并发编程实战知识点概述 #### 一、Java并发特性详解 在《Java并发编程实战》这本书中,作者深入浅出地介绍了Java 5.0和Java 6中新增的并发特性。这些特性旨在帮助开发者更高效、安全地编写多线程程序。书中...
Java并发编程是Java开发中的重要领域,特别是在多核处理器和分布式系统中,高效地利用并发可以极大地提升程序的性能和响应速度。这份“java并发编程内部分享PPT”显然是一个深入探讨这一主题的资料,旨在帮助开发者...
《Java并发编程实践》是一本深入探讨Java多线程编程的经典著作,由Brian Goetz、Tim Peierls、Joshua Bloch、Joseph Bowles和David Holmes等专家共同编写。这本书全面介绍了Java平台上的并发编程技术,是Java开发...
Java并发编程是Java开发者必须掌握的关键技能之一,它涉及到如何在多线程环境中高效、安全地执行程序。并发编程能够充分利用多核处理器的计算能力,提高应用程序的响应速度和整体性能。《Java编程并发实战》这本书是...
本资料“Java并发编程设计原则和模式”深入探讨了如何在Java环境中有效地进行并发处理,以充分利用系统资源并避免潜在的并发问题。 一、并发编程基础 并发是指两个或多个操作在同一时间段内执行,但并不意味着这些...
1.2.3 异步事件的简化处理 1.2.4 响应更灵敏的用户界面 1.3 线程带来的风险 1.3.1 安全性问题 1.3.2 活跃性问题 1.3.3 性能问题 1.4 线程无处不在 第一部分 基础知识 第2章 线程安全性 2.1 什么是线程安全...
根据提供的文件信息,“JAVA并发编程实践 中文 高清 带书签 完整版 Doug Lea .pdf”,我们可以推断出这份文档主要聚焦于Java并发编程的技术实践与理论探讨。下面将从多个角度来解析这个文档可能涵盖的关键知识点。 ...
Java并发编程是Java开发中的重要领域,特别是在大型分布式系统、多线程应用和服务器端程序设计中不可或缺。这个资源包“Java并发编程从入门到精通源码.rar”显然是为了帮助开发者深入理解并掌握这一关键技能。它包含...
根据给定文件的信息“JAVA并发编程实践”以及其描述为“Java并发学习资料”,我们可以从中提炼出关于Java并发编程的一些核心知识点。Java并发编程是Java高级特性之一,它允许开发者编写能够同时执行多个任务的程序,...
### Java 并发核心编程知识点解析 #### 一、Java并发概述 自Java诞生之初,其设计者就赋予了该语言强大的并发处理能力。Java语言内置了对线程和锁的支持,这...理解和掌握这些概念和技术是成功进行并发编程的关键。
Java并发编程中的多线程协作机制 在 Java 并发编程中,多线程协作机制是非常重要的一部分。多线程协作机制是指在多线程编程中,多个线程之间如何协作、同步和通信,以达到共同完成某个任务的目的。Java 提供了多种...
Java并发编程是指在Java语言中编写多线程和多任务执行的程序,以便更高效地利用计算机的多核处理器资源。并发编程是Java高级编程技能中的重要组成部分,尤其是在需要处理大量数据、提供快速响应、实现高吞吐量和高可...
《Java并发编程艺术》这本书是Java开发者深入理解多线程编程的重要参考资料。它全面而深入地探讨了Java平台上的并发编程技术,对于提升程序性能、优化系统资源利用以及解决多线程环境中的复杂问题有着极大的帮助。...
根据提供的文件信息:“JAVA并发编程实战.pdf”,我们可以深入探讨与Java并发编程相关的多个核心知识点。 ### Java并发编程基础 #### 1. 并发与并行 - **并发(Concurrency)**:指一个程序中存在多个执行序列(如...
《Java并发编程实践》这本书是Java开发者深入理解并发编程的重要参考资料。并发和多线程是现代计算机系统中不可或缺的部分,特别是在Java这样的多线程支持语言中。本书详细介绍了如何在Java环境中有效地设计和实现...
通过上述内容的学习,我们不仅掌握了Java并发编程的基本理论知识,还了解了如何在实际项目中应用这些技术来提升系统的并发处理能力。希望这些知识点能够帮助大家更好地理解和掌握Java并发编程的核心概念和技术要点。
5. **jcip-annotations-src.jar** 可能包含了Java并发编程实践书籍中使用的自定义注解,例如`@ThreadSafe`表示类是线程安全的,`@NotThreadSafe`表示类不是线程安全的,`@GuardedBy`指定一个字段由哪个锁保护等。...
总结而言,《Java并发编程实践》作为一本关于Java并发编程的经典书籍,通过理论讲解和实践案例相结合的方式,全面地向读者介绍了如何在Java中实现高效的并发程序设计,为开发者提供了丰富的工具和策略来处理多线程...