1. 模式概念
搜索是几乎每一个软件都必不可少的功能。对于有序数据,通常可以采用二分查找法。
对于无序数据,则只能挨个查找。在本节中,我们将讨论有关并行的无序数组的搜索实现。
给定一个数组,我们要查找满足条件的元素。对于串行程序来说,只要遍历一下数组就可以得到结果。
但如果要使用并行方式,则需要额外增加一些线程间的通信机制,使各个线程可以有效地运行。
2.程序代码01
//切分数据多线程
package com.john.learn.high.concurent.ch04.paralelsearch;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
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;
import java.util.concurrent.atomic.AtomicInteger;
public class ParalelSearcher1 {
private static final ExecutorService executorService = Executors.newCachedThreadPool();
public static int indexOf(String[] sources, String target) {
try {
return indexOf(sources, target, 10);
} finally {
executorService.shutdown();
}
}
public static int indexOf(String[] sources, String target, int parallelSize) {
int batch = sources.length / parallelSize + 1;
List> futures = new ArrayList<>();
// 123456789 3
// 123 456 789
for (int i = 0; i < sources.length; i += batch) {
int end = Math.min(i + batch, sources.length);
futures.add(executorService.submit(new Searcher(sources, i, end, target)));
if (end == sources.length) {
break;
}
}
for (Future future : futures) {
try {
if (future.get() >= 0) {
return future.get();
}
} catch (InterruptedException e) {
} catch (ExecutionException e) {
}
}
return -1;
}
private static class Searcher implements Callable {
private static final AtomicInteger Search_Result_IndexOf = new AtomicInteger(-1);
public Searcher(String[] sources, int start, int end, String target) {
this.sources = sources;
this.start = start;
this.end = end;
this.target = target;
}
@Override
public Integer call() throws Exception {
for (int i = start; i < end; i++) {
if (Search_Result_IndexOf.get() != -1) {
return Search_Result_IndexOf.get();
}
if (target.equals(this.sources[i])) {
if (!Search_Result_IndexOf.compareAndSet(-1, i)) {
return Search_Result_IndexOf.get();
}
return i;
}
}
return -1;
}
private String[] sources;
private int start;
private int end;
private String target;
}
public static void main(String[] args) throws InterruptedException {
String[] arr = new String[9000000];
Random random = new Random();
for (int i = 0; i < arr.length; i++) {
arr[i] = RandomUtils.nextLetters(4);
}
String target = RandomUtils.nextLetters(4);
Thread thread1 = new Thread() {
public void run() {
System.out.println("Thread 1 : index of " + indexOf());
};
private int indexOf() {
long start = System.currentTimeMillis();
for (int i = 0; i < arr.length; i++) {
if (target.equals(arr[i])) {
return i;
}
}
return -1;
}
};
Thread thread2 = new Thread() {
public void run() {
System.out.println("Thread2 index of :" + ParalelSearcher1.indexOf(arr, target));
};
};
thread1.start();
thread2.start();
thread1.join();
thread2.join();
}
}
3. 程序代码02
//原子索引多线程
package com.john.learn.high.concurent.ch04.paralelsearch;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
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;
import java.util.concurrent.atomic.AtomicInteger;
public class ParalelSearcher2 {
private static final ExecutorService executorService = Executors.newCachedThreadPool();
public static int indexOf(String[] sources, String target) {
return indexOf(sources, target, 100);
}
public static void shutdown() {
executorService.shutdown();
}
public static int indexOf(String[] sources, String target, int parallelSize) {
final AtomicInteger Search_Result_IndexOf = new AtomicInteger(-1);
final AtomicInteger index = new AtomicInteger(-1);
int batch = sources.length / parallelSize + 1;
List> futures = new ArrayList<>();
// 123456789 3
// 123 456 789
for (int i = 0; i < sources.length; i += batch) {
int end = Math.min(i + batch, sources.length);
futures.add(executorService.submit(new Searcher(Search_Result_IndexOf, index, sources, target)));
if (end == sources.length) {
break;
}
}
for (Future future : futures) {
try {
if (future.get() >= 0) {
return future.get();
}
} catch (InterruptedException e) {
} catch (ExecutionException e) {
}
}
return -1;
}
private static class Searcher implements Callable {
public Searcher(AtomicInteger Search_Result_IndexOf, AtomicInteger index, String[] sources, String target) {
this.Search_Result_IndexOf = Search_Result_IndexOf;
this.index = index;
this.sources = sources;
this.target = target;
}
@Override
public Integer call() throws Exception {
int j = sources.length;
int i = -1;
while ((i = index.incrementAndGet()) < j) {
if (Search_Result_IndexOf.get() != -1) {
return Search_Result_IndexOf.get();
}
if (target.equals(this.sources[i])) {
if (!Search_Result_IndexOf.compareAndSet(-1, i)) {
return Search_Result_IndexOf.get();
}
return i;
}
}
return -1;
}
private String[] sources;
private String target;
private AtomicInteger Search_Result_IndexOf;
private AtomicInteger index;
}
public static void main(String[] args) throws InterruptedException {
String[] arr = new String[9000000];
Random random = new Random();
for (int i = 0; i < arr.length; i++) {
arr[i] = RandomUtils.nextLetters(4);
}
ParalelSearcher2.indexOf(arr, RandomUtils.nextLetters(4));
String[] targets = new String[50];
for (int i = 0; i < targets.length; i++) {
targets[i] = RandomUtils.nextLetters(8);
}
Thread thread1 = new Thread() {
public void run() {
long start = System.currentTimeMillis();
for (int i = 0; i < targets.length; i++) {
int result = indexOf(targets[i]);
}
System.out.println("Thread 1 : cost:" + (System.currentTimeMillis() - start)/);
};
private int indexOf(String target) {
for (int i = 0; i < arr.length; i++) {
if (target.equals(arr[i])) {
return i;
}
}
return -1;
}
};
Thread thread2 = new Thread() {
public void run() {
long start = System.currentTimeMillis();
for (int i = 0; i < targets.length; i++) {
int result = ParalelSearcher2.indexOf(arr, targets[i]);
}
System.out.println("Thread 2 : cost:" + (System.currentTimeMillis() - start));
};
};
thread1.start();
thread2.start();
thread1.join();
thread2.join();
ParalelSearcher2.shutdown();
}
}