来自Effective Java(第10章并发)
假设您要在同步区域内调用外来方法,而受同步区域保护的不变量暂时无效.因为Java编程语言中的锁是可重入的,所以这样的调用不会死锁
现在看下面的代码:
// Broken - invokes alien method from synchronized block!
public class ObservableSet<E> extends ForwardingSet<E> {
public ObservableSet(Set<E> set) {
super(set);
}
private final List<SetObserver<E>> observers = new ArrayList<SetObserver<E>>();
private void notifyElementAdded(E element) {
synchronized (observers) {
for (SetObserver<E> observer : observers)
observer.alienMethod(this, element);
}
}
}
Run Code Online (Sandbox Code Playgroud)
因此,考虑SetObservers与ObservableSet两个独立编写的类和他们居住在不同的封装,因此alienMethod()的SetObserver是陌生的ObservableSet班级.现在说观察者在alienMethod被叫时不处于一致状态.那么折返锁的问题何在?如果外星人方法也在同一个锁上同步,即"观察者",那么重入只会产生问题,但这似乎不是这里的情况,或者我在这里遗漏了什么?
下面的代码试图将随机值插入循环队列并将其删除.但是,存在一些同步问题.我知道我可以使用更高级别的例程,我将为生产代码执行此操作,但我很好奇为什么这不起作用?我在这里错过了什么?
public class CircularQueue {
int count;
int rear;
int front;
Object lock = new Object();
int size;
int[] array;
CircularQueue(int size)
{
this.size= size;
array = new int[size];
}
void enqueue(int number) throws InterruptedException
{
if(isFull())
lock.wait();
synchronized(lock)
{
array[rear] = number;
System.out.println("Rear is:"+ rear+ "value is:"+number+"Size is:"+size);
rear = (rear+1)%size;
count++;
}
lock.notify();
}
void dequeue() throws InterruptedException
{
if(isEmpty())
lock.wait();
synchronized(lock)
{
int retVal = 0;
retVal = array[front];
System.out.println("Front is:"+ front+ "value is:"+retVal);
front = (front+1)%size; …Run Code Online (Sandbox Code Playgroud) 在使用时,java.util.concurrent.ThreadPoolExecutor我想再次尝试执行一个被拒绝的任务。真的有可能吗?我听说过RejectedExecutionHandler接口。接口(RejectedExecutionHandler)有许多可用(已知)实例,例如 ThreadPoolExecutor.AbortPolicy、ThreadPoolExecutor.CallerRunsPolicy、ThreadPoolExecutor.DiscardOldestPolicy、ThreadPoolExecutor.DiscardPolicy 等,但问题是它们不允许重试执行。
来自这个问题:AtomicInteger lazySet vs. set并形成此链接:https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/atomic/package-summary.html
我可以收集以下几点
我可以从文档中找到一个可以应用它的用例:
lazySet 还有其他实际用例吗?
我有一个ExecutorService将计算数据转发到 a CompletableFuture:
class DataRetriever {
private final ExecutorService service = ...;
public CompletableFuture<Data> retrieve() {
final CompletableFuture<Data> future = new CompletableFuture<>();
service.execute(() -> {
final Data data = ... fetch data ...
future.complete(data);
});
return future;
}
}
Run Code Online (Sandbox Code Playgroud)
我希望客户/用户能够取消任务:
final DataRetriever retriever = new DataRetriever();
final CompletableFuture<Data> future = retriever().retrieve();
future.cancel(true);
Run Code Online (Sandbox Code Playgroud)
这是行不通的,因为这会取消CompletableFuture执行程序服务中计划的外部未来,但不会取消内部未来。
cancel()是否有可能以某种方式将外部未来传播到内部未来?
新提交Java并发框架的方法.想知道在我调用submit或者调用get时线程是否被执行了?研究了Oracle官方文档,但找不到太多信息.谢谢.
我指的是下面的示例,
http://www.vogella.com/tutorials/JavaConcurrency/article.html
package de.vogella.concurrency.callables;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class CallableFutures {
private static final int NTHREDS = 10;
public static void main(String[] args) {
ExecutorService executor = Executors.newFixedThreadPool(NTHREDS);
List<Future<Long>> list = new ArrayList<Future<Long>>();
for (int i = 0; i < 20000; i++) {
Callable<Long> worker = new MyCallable();
Future<Long> submit = executor.submit(worker);
list.add(submit);
}
long sum = 0;
System.out.println(list.size());
// now retrieve the result
for (Future<Long> future : …Run Code Online (Sandbox Code Playgroud) for (int i=0; i<100000; i++) {
// REST API request.
restTemplate.exchange(url, HttpMethod.GET, request, String.class);
}
Run Code Online (Sandbox Code Playgroud)
我有一种情况,我必须为10万用户请求一个资源,它需要70分钟才能完成.我试图尽可能地清理我的代码,我只能将它减少4分钟).
由于每个请求彼此独立,我很乐意并行发送请求(可能是10s,100s甚至1000s的块,每次快速完成).我希望我能把时间减少到10分钟或者接近的时间.如何计算哪个块大小可以快速完成工作?
我找到了以下方法,但我不知道该程序是否一次处理所有20个; 或一次5个; 或者一次10个.
IntStream.range(0,20).parallel().forEach(i->{
... do something here
});
Run Code Online (Sandbox Code Playgroud)
我知道你的帮助.我对任何建议或评论都持开放态度!
更新:我能够使用IntStream,并在28分钟内完成任务.但我不确定这是我能做的最好的.
java parallel-processing concurrency java.util.concurrent java-8
Brian Goetz的Java Concurrency实践提供了一个用于并发使用的高效可伸缩缓存的示例.显示类Memoizer(第108页)实现的示例的最终版本显示了这样的缓存.我想知道为什么有一个内部和外部检查if(f == null).第二个没有任何意义,因为:
这是Memoizer的代码:
public class Memoizer<A, V> implements Computable<A, V> {
private final ConcurrentMap<A, Future<V>> cache
= new ConcurrentHashMap<A, Future<V>>();
private final Computable<A, V> c;
public Memoizer(Computable<A, V> c) { this.c = c; }
public V compute(final A arg) throws InterruptedException {
while (true) {
Future<V> f = cache.get(arg);
if (f == null) {
Callable<V> eval = new Callable<V>() {
public V call() throws InterruptedException {
return c.compute(arg);
}
};
FutureTask<V> ft = new FutureTask<V>(eval); …Run Code Online (Sandbox Code Playgroud) java concurrency thread-safety concurrenthashmap java.util.concurrent
我想在我的 Spring Boot 项目中使用 ForkJoinPool 和 @Async 注释,比如 ThreadPoolTaskExecutor
例如 :-
@Bean("threadPoolTaskExecutor")
public TaskExecutor getAsyncExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(20);
executor.setMaxPoolSize(1000);
executor.setThreadNamePrefix("Async-");
return executor;
}
Run Code Online (Sandbox Code Playgroud)
我在我的代码中使用https://dzone.com/articles/spring-boot-creating-asynchronous-methods-using-作为这个链接,但我想像这样使用 ForkJoinPool 。
我正在创建一个调度程序并以 2 秒的延迟安排作业。但在安排特定作业之前,我想检查 ScheduledExecutorService 的池大小和队列大小,但我找不到任何方法。任何人都可以向我建议如何在安排任何作业之前检查 ScheduledExecutorService 的池大小和队列大小。
//here i have created ScheduledExecutorService
private static final ScheduledExecutorService SCHEDULED_EXECUTOR_SERVICE;
static {
//initialized ScheduledExecutorService with 30 pool size
Scheduled_Executor_Service = (ThreadPoolExecutor) Executors.newScheduledThreadPool(30);
}
public void addTaskTOSchedule(){
//Here i want to check poolsize and queue size of SCHEDULED_EXECUTOR_SERVICE if
//ScheduledExecutorService already used more then specific number thread then i will not schedule job
SCHEDULED_EXECUTOR_SERVICE.schedule(() -> {
User user = new User();
SCHEDULED_EXECUTOR_SERVICE.execute(user);
}, 2000, TimeUnit.MILLISECONDS);
}
Run Code Online (Sandbox Code Playgroud)