写代码(×)
整活(√)
灵感来源于B站up主-“IT楠老师”
首先,根据IT楠老师的思想,每遍历到一个数组中的数字的时候,就新建立一个线程,然后让这个线程休眠与数字大小相等的时间,休眠之后将这个数字输出,那么,数字比较小的就先结束休眠就会先行输出,而数字比较大的就会慢一步输出了,从而达到排序的效果
照着up主的方法写了一遍:
public static void sleepSort(int nums){
for(int i=0;i<nums.length;i++){
final int num = nums[i];
new Thread(()->{
try {
Thread.sleep(num);
} catch (InterruptedException e) {
e.printStackTace();
}
System.out.println(num);
}).start();
}
}
但是,既然都是多线程并发排序算法了,竟然还在使用for循环遍历列表,这就显得很low
所以我决定使用了泛型列表List+forEach()来遍历这个列表
而且,我决定还要在forEach()中使用lambda表达式来显得算法更加高级(可惜不能用双冒号运算符)
而这样写的后果就是导致括号里面还嵌套了很多括号和大括号
最后写出来是这样的:
public class SortUtil {
private static ReentrantLock lock = new ReentrantLock();
private static Condition sufficientFunds = lock.newCondition();
public static void main(String[] args) {
Integer[] arr = {1, 7, 3, 9, 43, 45, 23, 18, 16, 33};
sleepSort(arr);
}
public static void sleepSort(Integer[] arr) {
List<Integer> list = Arrays.asList(arr);
list.forEach(t->{
new Thread(()-> {
try {
Thread.sleep(t);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(t);
}
).start();
}
);
}
}
到了这一步,我觉得还是不够,既然是多线程,我们就要考虑线程带来的一些问题
比如说
Thread.sleep(t)这一段代码,对于每一个t,并不是在同一时间开始执行的,比如遍历到第十个t时,必须要等到第九个t进入休眠后才能执行第十个t的休眠操作,虽然这两个之间的时间间隔极端极端,但是如果数组长度变大,聚少成多,这种差异就无法忽略了(滑稽)
所以我们要做的,就是尽量减少这种差异
所以,我的思路是,每遍历到一个新的t时,就检测这个t是不是List的最后一位,如果不是,就让线程进入等待状态,直到遍历到List最后一位的时候,就让所有线程恢复,同时开始休眠
这样的话,是不是就免去了遍历数组带来的时间差异(maybe,其实我也不太确定)
所以我给这段代码增加了锁和条件对象的机制
public class SortUtil {
private static ReentrantLock lock = new ReentrantLock();
private static Condition sufficientFunds = lock.newCondition();
public static void main(String[] args) {
Integer[] arr = {1, 7, 3, 9, 43, 45, 23, 18, 16, 33};
sleepSort(arr);
}
public static void sleepSort(Integer[] arr) {
List<Integer> list = Arrays.asList(arr);
list.forEach(t->{
new Thread(()-> {
try {
lock.lock();
int i = 0;
while(i == 0 && t != arr[arr.length - 1]) {
i++;
System.out.println("等待遍历");
sufficientFunds.await();
}
sufficientFunds.signalAll();
System.out.println("开始排序");
lock.unlock();
Thread.sleep(t);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(t);
}
).start();
}
);
}
}
好像和一般的多线程使用方法不一样呢……
这样写,我也不知道到底有没有用,也不知道到底这样写符不符合规范
但是代码是能跑而且正确输出的(艹),毕竟程序和人能跑一个就对了
测试一下