在Java中,我想做这样的事情:
Object r = map.get(t);
if (r == null) {
r = create(); // creating r is an expensive operation.
map.put(t, r);
}
Run Code Online (Sandbox Code Playgroud)
现在,代码片段可以在多线程环境中执行.
map可以是ConcurrentHashMap.
但是我如何使逻辑成为原子?
请不要像"同步"块那样给我一些简单的解决方案.我希望这个问题可以一劳永逸地解决.
我正在浏览ConcurrentHashMapjdk 7中的源代码并且几乎没有问题.我已经在StackOverFlow上完成了有关CHM的所有问题,但找不到答案.
get()CHM中的操作是否保证put()由其他线程获得正确的值?我问这是因为get不是,synchronized除非它看到null值.null值如何确保其他线程正在更新相同的记录然后get与lock一起使用?
这与HashEntry存储键和值的静态类有关.
一个.为什么这堂课最后?它只是为了确保没有人对它进行子类化吗?如果有人将其子类化,会发生什么 - 这有什么问题?
湾 如何使下一个字段最终有助于获得线程安全?
C.为什么Key也是最终的?(我不确定为什么Key也是最终的HashMap)
java collections multithreading concurrenthashmap java.util.concurrent
我的主线程中有一个函数,它会将一些数据写入磁盘.我不希望我的主线程卡住(磁盘I/O的高延迟)并且创建一个新线程只是为了写入是一个矫枉过正.我决定使用ExecutorService.
ExecutorService executorService = Executors.newFixedThreadPool(3);
Future future = executorService.submit(new Callable<Boolean>() {
public Boolean call() throws Exception {
logger.log(Level.INFO, "Writing data to disk");
return writeToDisk();
}
});
Run Code Online (Sandbox Code Playgroud)
writeToDisk是写入磁盘的函数
这是一个很好的方式吗?有人可以提出更好的方法吗?
更新:数据大小将大于100 MB.磁盘带宽为40 MBps,因此写入操作可能需要几秒钟.我不希望调用函数卡住,因为它必须做其他工作,所以,我正在寻找一种方法来调度磁盘I/O异步执行调用线程.
我需要委派任务而忘记它!
我一直在使用ReadWriteLock来实现/维护锁定习语.
自JDK8 StampedLock推出以来.由于RWLocks以其缓慢和糟糕的性能而闻名,因此StampedLock看起来像是另一种选择(它们不是可重入的,速度更快).
然而,除了性能之外,我认为StampedLock的维护和使用更加困难和复杂 - 例如线程现在可以自行解锁 - 因此应采取相应的措施.
StampedLock比RWLock有什么好处?
这是java.util.concurrent.CountedCompleter类的代码片段(JDK 1.8.0_25).
/**
* If the pending count is nonzero, decrements the count;
* otherwise invokes {@link #onCompletion(CountedCompleter)}
* and then similarly tries to complete this task's completer,
* if one exists, else marks this task as complete.
*/
public final void tryComplete() {
CountedCompleter<?> a = this, s = a;
for (int c;;) {
if ((c = a.pending) == 0) {
a.onCompletion(s);
if ((a = (s = a).completer) == null) {
s.quietlyComplete();
return;
}
}
else if …Run Code Online (Sandbox Code Playgroud) 我有一个程序,有一个ConcurrentHashMap不同的线程可以添加/删除地图中的项目.
我很想知道在25个项目中读取地图的最佳方法是什么.我想要做的是这样的:用户点击按钮并从地图中读取25个项目(与订单无关).之后,他可以单击"下一步"按钮并读取另外25个项目(与前25个项目不同),依此类推.
我不确定我是否可以这样做ConcurrentHashMap.我不想使用数据库,我想把它保存在内存中.我不认为转换Map成一个ArrayList会有帮助,因为大多数时候都会在地图中添加/删除项目.
我愿意接受任何解决方案,甚至是第三方库.
更新:我也没有被束缚ConcurrentHashMap.我只是在寻找最好的解决方案
更新2:他们的钥匙是String
谢谢
我有一个应用程序,我想确保一个方法最多同时调用一次,比如在数据库中更新用户余额时.
我正在考虑使用以下锁定机制:(显示下面的Scala代码,但应该与Java Lambdas类似):
object Foo{
val dbLocked = new java.util.concurrent.atomic.AtomicBoolean(false)
def usingAtoimcDB[T](f: => T):T = {
if (dbLocked.get) throw new Exception("db is locked")
dbLocked.set(true)
try f
finally dbLocked.set(false)
}
}
Run Code Online (Sandbox Code Playgroud)
usingAtoimcDB可以同时调用时使用是否安全?
编辑:下面更正的代码,如下面的答案所示:
def usingAtoimcDB[T](f: => T):T = {
if(dbLocked.compareAndSet(false, true)) {
//db is now locked
try f
finally dbLocked.set(false)
} else {
//db is already locked
throw new Exception("db is locked")
}
}
Run Code Online (Sandbox Code Playgroud)
编辑2:
使用spinloop.这也行吗?
def usingAtoimcDB[T](f: => T):T = {
while (!dbLocked.compareAndSet(false, true)) {Thread.sleep(1)}
try f …Run Code Online (Sandbox Code Playgroud) 我试图在java 8中学习并发和lambdas.但是我的代码没有在map中输入lambda块.
List<Book> bookList = new ArrayList<Book>();
isbnList
.stream()
.map(isbn -> (CompletableFuture.supplyAsync( () -> {
try {
List<String> pageContents = getUrlContents(webLink + isbn);
return new Book(
parseBookTitle(pageContents),
isbn,
parseRank(pageContents)
);
} catch (IOException ex) {
return null;
}
})).thenApply(a -> bookList.add(a))
);
Run Code Online (Sandbox Code Playgroud)
在调试时,代码退出.map行,我得到空bookList.顺序代码给我正确的结果.
concurrency lambda java.util.concurrent java-8 concurrent.futures
我有一个java模块,它需要通过接口同时执行一组任务(为实现模块的框架提供低级控制和处理),但同时不是太多,java.util.concurrent.Semaphore似乎是完美的.
我不确定的一个问题是线程安全release()和acquire()调用.一个线程可以获取信号量锁,后来另一个线程释放它吗?
考虑以下服务类别:
//Singleton service
public class InquiryService{
private final ExecutorService es = Executors. newSingleThreadExecutor();
private final CustomerService cs = new CustomerServiceImpl();
public String process(){
//Asynchronous calls to get info from CustomerService
Future<String> result = es.submit(()->{return cs.getCustomer()});
//Query database
//Perform logic et all
String customerName = result.submit.get();
//continue processing.
}
}
Run Code Online (Sandbox Code Playgroud)
上面的服务类具有一个ExecutorServiceas字段。如果说在process方法上有100个并发请求,那么剩下的(100-1)个请求是否需要等待线程可用性?
如何解决请求等待?我可以想到的一种选择是ExecutorService在process方法内实例化,使用和关闭。但是,线程池不是要重用吗?
另一个选项将作为运行new Thread(new FutureTask<>(() -> {return cs.getCustomer()}))。哪一种是正确的方法?
更新:-
根据评论和答案,ExecutorService要重用和频繁Thread创建新内容的成本很高。因此,另一个选择是依次运行服务调用。