支持有几个线程运行查询任务,每个线程都会返回一个list结果,哪种数据结构会更快地合并结果?
基于链接节点的无界线程安全队列。该队列对元素进行 FIFO(先进先出)排序。队列的头部是在队列中停留时间最长的元素。队列的尾部是在队列中停留时间最短的元素。新元素插入到队列尾部,队列检索操作获取队列头部元素。当许多线程共享对公共集合的访问时,ConcurrentLinkedQueue 是一个合适的选择。与大多数其他并发集合实现一样,此类不允许使用 null 元素。 该实现采用了一种高效的“无等待”算法,该算法基于 Maged M. Michael 和 Michael L. Scott 的《简单、快速和实用的非阻塞和阻塞并发队列算法》中描述的算法。
顾名思义,CopyOnWriteArrayList 使用每个突变操作(例如添加或设置)创建底层 ArrayList 的副本。通常,CopyOnWriteArrayList 非常昂贵,因为它在每次写入操作时都涉及昂贵的数组复制,但如果您有一个迭代次数超过突变的列表,则它非常有效,例如您主要需要迭代 ArrayList 并且不要太频繁地修改它。
java concurrency multithreading java.util.concurrent copyonwritearraylist
我正在阅读有关包装器实现的java官方文档,它们是集合中用于获取同步集合的静态方法,例如:List<Type> list = Collections.synchronizedList(new ArrayList<Type>());
...
我不明白的事情如下(我引用自java文档):
以这种方式创建的集合与通常同步的集合(例如 Vector)一样是线程安全的。面对并发访问,用户在迭代返回的集合时必须手动同步它。原因是迭代是通过对集合的多次调用来完成的,必须将其组合成单个原子操作......
它如何能够是线程安全的,并且需要在迭代时手动同步?
我有两个 Java 文件:
检查.java
import java.util.concurrent.Semaphore;
class Check
{
public static void main(String[] args)
{
Semaphore s = new Semaphore(1);
MyThread t1 = new MyThread("t1",s);
MyThread t2 = new MyThread("t2",s);
t1.start();
t2.start();
t2.interrupt();
}
}
Run Code Online (Sandbox Code Playgroud)
MyThread.java
import java.util.concurrent.Semaphore;
class MyThread extends Thread
{
Semaphore s;
MyThread(String name, Semaphore s)
{
super(name);
this.s=s;
}
public void run()
{
try
{
s.acquireUninterruptibly();
for(int i=0; i<5; i++)
{
Thread.sleep(500);
System.out.println(Thread.currentThread().getName()+"-"+i);
}
s.release();
}
catch(InterruptedException e){}
}
}
Run Code Online (Sandbox Code Playgroud)
如果我注释掉语句“t2.interrupt()”,那么两个线程都可以正常执行。但如果我不评论该语句,那么线程 t2 根本不会执行。根据我对 acquireUninterruptically() 方法的理解,线程 t2 …
我一直在浏览java.util.concurrent包,并试图了解库提供给我们的内容.我遇到CopyOnWriteArrayList并ConcurrentHashMap上课并试图找到这些条款如何实现线程安全.因为CopyOnWriteArrayList它非常直观,只要有写操作,就可以通过创建底层数组的新副本来实现它们.但是,我无法理解如何ConcurrentHashMap实现线程安全,同时提供并发性?
编辑:如果有人能告诉我实施背后的概念就足够了.考虑到这一点,我可以深入研究源代码,从而帮助我以更好的方式和结构化的方式理解它.
请参阅以下代码段(剥离冗余部分以突出显示有问题的情况):
FindBugs抱怨" 方法不会释放所有路径上的锁定 ".这是误报吗?如果没有,如何解决这个问题?
try{
someLock.lock();
//do something
} finally{
if (someLock.isLocked())
someLock.unlock();
}
Run Code Online (Sandbox Code Playgroud) 据我所知,ThreadLocal变量为每个线程维护一个单独的变量副本.保持多个副本的此变量本质上是一个共享变量.那么说变量值可以有多个副本是什么意思呢?如何保持一致性,以使副本的值不会失去同步?
java multithreading thread-safety thread-local java.util.concurrent
如何使用java.util.concurrency 实现" fire and forget "行为?我试过了:
ExecutorService executor = Executors.newSingleThreadExecutor();
public void push(Callable<Boolean> task) {
Future<Boolean> future = executor.submit(task);
future.get(timeout, timeoutUnit);
}
Run Code Online (Sandbox Code Playgroud)
但是get()阻止直到完成.该push()来电者是不感兴趣的任务的结果.
我有一个Web测试应用程序(基于Selenium,但这在这里应该不重要),它连续执行了大量的测试用例.这需要几个小时才能完成,测试用例数量会增加,所以我想使用多个Web浏览器实例并行执行多个测试用例.测试用例彼此之间没有依赖关系.
非常简化它看起来像这样:
TestExecutor executor = new TestExecutor(new FirefoxDriver());
for (TestCase test: tests) {
executor.execute(test);
// use results here
}
Run Code Online (Sandbox Code Playgroud)
现在我不确切知道如何并行化这个.我可以轻松地创建几个连接到几个Web浏览器的TestExecutors作为Callables并使用Executors,CompletitionServices和其他好帮手类,但我该如何:
一旦它准备好使用之前的TestCase,就将新的TestCase传递给TestExecutor?Callable中的call()方法不带参数,所以我可能必须在我的TestExecutor类中实现一些setNextTestCase()来实现这个我觉得不太好的.还有更好的选择吗?
重用TestExecutor实例来执行下一个测试用例?由于每个TestExecutor实例都需要一个Web浏览器实例,因此如果我为每个测试用例创建一个新的TestExecutor,则需要很长时间来初始化它并导致许多窗口在屏幕上闪烁.
我可以通过提供代码片段来解释我的问题:
public static void main(final String[] a) {
Stream.of(1, 2, 3, 4).map(i -> ForkJoinPool.commonPool().submit(new RecursiveAction() {
@Override
protected void compute() {
System.out.println(Thread.currentThread());
}
})).forEach(ForkJoinTask::join);
}
Run Code Online (Sandbox Code Playgroud)
在我的笔记本电脑上运行时,它有4个核心,这打印:
Thread[main,5,main]
Thread[ForkJoinPool.commonPool-worker-1,5,main]
Thread[main,5,main]
Thread[ForkJoinPool.commonPool-worker-1,5,main]
Run Code Online (Sandbox Code Playgroud)
为什么某些任务在主线程中运行,主线程是公共fork连接线程池之外的线程?
创建自定义fork join线程池时,不会发生这种情况:
public static void main(final String[] a) {
final ForkJoinPool p = new ForkJoinPool(4);
Stream.of(1, 2, 3, 4).map(index -> p.submit(new RecursiveAction() {
@Override
protected void compute() {
System.out.println(Thread.currentThread());
}
})).forEach(ForkJoinTask::join);
}
Thread[ForkJoinPool-1-worker-1,5,main]
Thread[ForkJoinPool-1-worker-1,5,main]
Thread[ForkJoinPool-1-worker-1,5,main]
Thread[ForkJoinPool-1-worker-1,5,main]
Run Code Online (Sandbox Code Playgroud)
那么,换句话说,公共池有什么特别之处?提供这些知识,在公共池中执行长时间运行的任务是明智的还是不明智的想法?
我有2种方法,这些方法具有要同时运行的不同返回类型。这是我的代码:
public void method(int id) {
final CompletableFuture<List<FooA>> fooACF = CompletableFuture.supplyAsync(() -> generateFooA(id));
final CompletableFuture<List<FooB>> fooBCF = CompletableFuture.supplyAsync(() -> generateFooB(id));
List<FooA> fooAs = fooACF.get();
List<FooB> fooBs = fooBCF.get();
//Do more processesing
}
public List<FooA> generateFooA(int id) {
//code
}
public List<FooB> generateFooB(int id) {
//code
}
Run Code Online (Sandbox Code Playgroud)
但是我不知道这两种方法是否都可以与上面的代码并行运行,或者我是否更好地说:
List<FooA> fooAs = generateFooA(id);
List<FooB> fooBs = generateFooB(id);
Run Code Online (Sandbox Code Playgroud)
如何正确使用可完成的期货才能并行运行这两种方法?
java concurrency java.util.concurrent java-8 completable-future
java ×10
concurrency ×3
collections ×1
findbugs ×1
fork-join ×1
forkjoinpool ×1
java-8 ×1
semaphore ×1
thread-local ×1