java实现并发搜索数组元素

来源:互联网 发布:python genetic 编辑:程序博客网 时间:2024/05/01 03:02

前言:搜索是很多软件不可或缺的功能。对于有序的数组,我们可以采用常见的二分查找法,对于无序的数据,只能是挨个查找。


如果说在线程充足的情况,可以考虑使用多线程思路去解决搜索问题,即并发搜索。

思路:将原来的数组按照线程数进行分割,当有两个线程搜索元素时,可以将数组一分为二,让每个线程在指定的角标范围内搜索元素,当其中有一个线程搜索到元素则,立即将结果返回。


代码如下:


import java.util.ArrayList;import java.util.List;import java.util.concurrent.Callable;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.concurrent.Future;import java.util.concurrent.atomic.AtomicInteger;public class Demo8 {static ExecutorService pool = Executors.newCachedThreadPool();static final int Thread_Num = 2;//假设数组的值都大于或等于0,当出现小于0的情况,可以设置一个无穷小的值或新增一个标志static AtomicInteger result = new AtomicInteger(-1);    public static int pSearch(int[] arr, int searchValue) throws Exception {    int subArrSize = arr.length / Thread_Num + 1;    List<Future<Integer>> re = new ArrayList<Future<Integer>>();    for (int i = 0, len = arr.length; i < len; i += subArrSize) {    //分割数组操作int end = i + subArrSize;if (end >= len) {end = len;}re.add(pool.submit(new SearchTask(arr, searchValue, i, end)));}    for (Future<Integer> fu : re) {    //Future接口的get()方法具有阻塞效果,当结果还没返回时则一直阻塞,直到返回结果if (fu.get() > 0) return fu.get();}    return -1;    }            /**     * 查询的方法     * @param arr 指定搜索的数组     * @param searchValue 搜索值     * @param beginPos 开始索引     * @param endPos 结束索引     * @return 所在角标     */    public static int search(int[] arr, int searchValue, int beginPos, int endPos) {    int i = 0;    for (i = beginPos; i < endPos; i++) {    //当大于0所以值已经被替换,直接返回结果    if (result.get() > 0) {    return result.get();    }    if (arr[i] == searchValue) {    //使用CAS原理,当更新失败则说明值已经被修改过,直接返回结果    if (!result.compareAndSet(-1, searchValue)) {    return result.get();    }    return i;    }}    return -1;    }        /**     * 自定义一个任务类,以便将数据封装到任务中     */    public static class SearchTask implements Callable<Integer> {    int begin, end, searchValue;    int[] arr;    public SearchTask(int[] arr, int searchValue, int begin, int end) {    this.begin = begin;    this.end = end;    this.searchValue = searchValue;    this.arr = arr;    }@Overridepublic Integer call() throws Exception {return search(arr, searchValue, begin, end);}    }}  



知识点补充:

1、CAS原理: 操作的时包含三个操作数 — 内存位置(V)、预期原值(A)和新值(B)。 如果内存位置的值与预期原值相匹配,那么处理器会自动将该位置值更新为新值。否则,处理器不做任何操作。

2、AtomicInteger相比于是具有原子性的Integer,它的compareAndSet方法采用的是CAS原理,所以第一次会设置成功,第二次起便会失败。

3、Future模式可以异步获取接口的数据,Future.get()当数据未完成时会阻塞,直到数据获取完成,或是设置超时时间。


结尾:笔者在使用家用机做测试的时候发现,并发搜索相对于普通搜索性能上没有很大的提升,甚至更差,所以想做测试的时候,尽量选线程较多的机器,还有数组的量尽量调大,这样效果比较明显。


参考自:《实战Java高并发程序设计》

0 0
原创粉丝点击