java多线程实现外排序_Java实现“睡排序”——线程池Executors的使用

前提

之前在知乎上看见一个有意思的排序算法——睡排序。

睡排序最早好像是4chan上一个用户用shell脚本实现的:

1f15af4de199f9630ce9400c3aff2a15.png

算法思想简洁明了:利用进程的sleep来实现 越大的数字越迟输出。

虽然像2L说的那样,这个算法没什么利用价值。但我打算试着用Java来实现一下这个“睡排序”。

Java实现

既然选择用Java来实现,我们就没必要为数组中每一个元素启一个进程,启多线程就够了。

Java启线程的方式有很多:1.继承Thread 2.实现Runnable 3.实现Callable ...

而当前需求是要同时启固定数量的多个线程,那么通过Executor提供的线程池来启线程最合适不过了。

下面是代码:

public static List sleepSort(int[] nums){

List res = new Vector<>(); // 1

ExecutorService executor=Executors.newFixedThreadPool(nums.length);

IntStream.of(nums).forEach(i-> executor.execute(() ->{try{

Thread.sleep(i* 200); // 2

}catch(InterruptedException e) {

e.printStackTrace();

}

res.add(i);

}));

executor.shutdown();while (true){ // 3if(executor.isTerminated())break;

}returnres;

}

几个注意点:

1. 作为一个排序方法只是打印结果的话未免有些单调,所以我打算返回一个List作为排序后的结果。因为涉及多线程的操作,这里选择线程安全的Vector。

2. forEach的遍历方式会使各个线程的启动时间有细微的差距,因此sleep的时间不能太多。经过测试,* 200(ms) 比较合适。

3. 在返回结果之前,必须保证所有线程执行完毕。注意 "executor.shutdown()" 只是关闭线程池,并不会终止线程。所以要通过 "executor.isTerminated()"来判断。

算法分析这个算法看起来的复杂度是O(nums.length)。 实际上,复杂度为O(n ^ 2 ),因为维护多个后台线程程依赖于CPU来管理进程的上下文切换和优先级,所以该算法基本上将实际排序外包给了CPU。

测试

写一个生成乱序数组的方法,用于生成测试用例。

public static int[] getRandomArray(int len, intmaxNum){int[] res = new int[len];

Random random= newRandom();for (int i=0;i

res[i]=random.nextInt(maxNum);

}returnres;

}public static voidmain(String[] args){

System.out.println(sleepSort(getRandomArray(18, 29)));

}

结果:

7e719cebfb675e49e2564522c2b72304.png

理论上数组的最大长度为当前JVM能创建的最大线程数:(系统CPU内存- JVM内存- 系统预留内存) / (线程栈的大小)

最后

该算法仅供娱乐,如何什么可以改进的地方,欢迎讨论。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值