目录

SleepSort

目录

我这里首先尝试了 ReentrantLock, 用它我本以为可以精确控制锁的粒度, 这里省去了一些非必要代码, 思路是创建一大堆线程然后全部等锁, 线程就绪之后再放开锁

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
public class SleepSort {
    final static ReentrantLock lock = new ReentrantLock();
    final static Condition condition = lock.newCondition();

    static volatile boolean locked = true;
    static volatile AtomicInteger index = new AtomicInteger(0);
    static int[] sleepInts;

    static Runnable getRunnable(int time) {
        return () -> {
            lock.lock();
            while (locked) condition.await();
            lock.unlock();
            Thread.sleep(time);
            sleepInts[index.getAndIncrement()] = time;
        };
    }

    static void sleepSort() {
        System.out.println("start sleep sort");
        long start = System.currentTimeMillis();
        ExecutorService executor = Executors.newFixedThreadPool(1000);
        for (int i = 0; i < 1000; i++) sleepInts[i] *= 21L;
        for (int i = 0; i < 1000; i++) executor.execute(getRunnable(sleepInts[i]));
        lock.lock();
        locked = false;
        condition.signalAll();
        lock.unlock();
        executor.shutdown();
        executor.awaitTermination(100000L, TimeUnit.DAYS);
        long time = System.currentTimeMillis() - start;
        System.out.println("end sleep sort: " + time);
        System.out.println("sleep sort examine: " + examine());
    }

    static boolean examine() {
        for (int i = 0; i < sleepInts.length - 1; i++)
            if (sleepInts[i] > sleepInts[i + 1]) return false;
        return true;
    }

    public static void main(String[] args) {
        final int[] ints = new int[1000];
        Random random = new Random();
        for (int i = 0; i < 1000; i++)
            ints[i] = random.nextInt(10);
        final int[] ints1 = new int[1000];
        for (int i = 0; i < 1000; i++)
            ints1[i] = random.nextInt(10);

        sleepInts = ints1;
        sleepSort();

        System.out.println("start Arrays sort");
        long start = System.currentTimeMillis();
        Arrays.sort(ints);
        long time = System.currentTimeMillis() - start;
        System.out.println("end Arrays sort: " + time);
    }
}

结果: 其中经过测试, 时间放大 21 倍才能确保排序结果正确(我的电脑上)….

1
2
3
4
5
start sleep sort
end sleep sort: 295
sleep sort examine: true
start Arrays sort
end Arrays sort: 0

我尝试换成了 synchronized:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
static Runnable getRunnable(int time) {
    return () -> {
        synchronized (o) {
            while (locked) {
                o.wait();
            }
        }
        Thread.sleep(time);
        sleepInts[index.getAndIncrement()] = time;
    };
}

static void sleepSort() {
    System.out.println("start sleep sort");
    long start = System.currentTimeMillis();
    ExecutorService executor = Executors.newFixedThreadPool(1000);
    for (int i = 0; i < 1000; i++) {
        sleepInts[i] *= 11L;
    }
    for (int i = 0; i < 1000; i++)
        executor.execute(getRunnable(sleepInts[i]));
    synchronized (o) {
        locked = false;
        o.notifyAll();
    }
    executor.shutdown();
    executor.awaitTermination(100000L, TimeUnit.DAYS);
    long time = System.currentTimeMillis() - start;
    System.out.println("end sleep sort: " + time);
    System.out.println("sleep sort examine: " + examine());
}

最低可以到放大 11 倍, 至于和 Arrays.sort 比, 那没事了

1
2
3
4
5
start sleep sort
end sleep sort: 192
sleep sort examine: true
start Arrays sort
end Arrays sort: 0