随着机器学习技术的不断发展,人工智能已经开始渗透到各个领域。其中,最引人注目的之一便是 AI 辅助编程工具。在这个领域里,Github Copilot 无疑是一颗闪耀的明星,它可以推荐代码片段、自动生成代码,并提供代码补全和建议等功能。Github Copilot 以插件的方式集成到IDA中,如果你的IDE找不到或无法安装这个插件,请升级软件版本。

目录

自己以前写的代码片段

Copilot 推荐的代码片段

完整代码


前年为应对项目中调用的一个接口限流问题,简单写了一个单机版的滑动窗口计数器。今天想让 Copilot 写一个,输入类名称后,它向我推荐的代码片段,竟然我和之前编写的一模一样。以下分别是以前写的代码片段(完整代码在文末),和 Copilot 推荐的代码片段。

自己以前写的代码片段

Copilot 推荐的代码片段

更有趣的是,Copilot 可以不断地学习和改进。细心的读者可能已经发现,前面两幅图中的代码有一点差异,是因为我对自己的代码进行了优化,去掉了第27行的 if。Copilot 也注意到了这一点,并更新自己的模型数据,不久后当我让 Copilot 重新推荐这个代码,并且即使我对自己的代码撤销了该优化,Copilot 仍向我推荐优化后的代码。

最后的main()方法,Copilot 没参考我以前的代码,只根据上下文生成,相比我自己写的要简单些。

完整代码

import java.time.Duration;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.Random;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;

/**
 * 滑动窗口计数器
 */
public class SlidingWindow {
    //滑动窗口元素数组
    private final WindowElement[] windowElements;
    //窗口长度
    private final int windowSize;
    //窗口期
    private final long windowDuration;
    //窗口精度
    private final long windowAccuracy;
    //时间戳
    private long ctm;

    //滑动窗口元素
    private class WindowElement {
        public AtomicLong num = new AtomicLong(0);
        public long ts = 0;
        public long incrAndGet() {
            synchronized (this) {
                if (ts < ctm - windowDuration) {
                    num.set(1);
                    ts = ctm;
                    return 1;
                }
            }
            return num.incrementAndGet();
        }
    }

    /**
     * 创建一个滑动窗口计数器
     * @param duration
     * @param accuracy
     */
    public SlidingWindow(Duration duration, Duration accuracy) {
        windowDuration = duration.toMillis();
        windowAccuracy = accuracy.toMillis();
        //窗口长度+1,确保窗口元素过期才会被覆盖
        windowSize = (int) Math.ceil(1.0 * duration.toMillis() / accuracy.toMillis()) + 1;
        windowElements = new WindowElement[windowSize];
        for (int i = 0; i < windowSize; i++) {
            windowElements[i] = new WindowElement();
        }
    }

    /**
     * 计数+1
     * @return
     */
    public long increment() {
        ctm = System.currentTimeMillis();
        int index = (int) ((ctm / windowAccuracy) % windowSize);
        return windowElements[index].incrAndGet();
    }

    /**
     * 计数+1并返回计数总和
     * @return
     */
    public long incrementAndGet() {
        long sum = increment();
        if (windowSize == 1) {
            return sum;
        } else {
            return Arrays.stream(windowElements).filter(e -> e.ts >= ctm - windowDuration).mapToLong(e -> e.num.get()).sum();
        }
    }

    /**
     * 返回窗口中所有计数总和
     * @return
     */
    public long getSum() {
        ctm = System.currentTimeMillis();
        return Arrays.stream(windowElements).filter(e -> e.ts >= ctm - windowDuration).mapToLong(e -> e.num.get()).sum();
    }

    public static void main(String[] args) {
        SlidingWindow window = new SlidingWindow(Duration.ofMillis(500), Duration.ofMillis(100));
        Random rand = new Random(System.currentTimeMillis());

        //创建一个线程,每50ms执行一次,输出当前窗口计数总和
        Thread thread = new Thread(() -> {
            while (true) {
                System.out.println(LocalDateTime.now() + " sum: " + window.getSum());
                try {
                    Thread.sleep(50);
                } catch (InterruptedException e) {
                    break;
                }
            }
        });
        thread.start();

        //创建5个线程,每个线程随机休眠0~100ms,随机执行+1操作
        ThreadPoolExecutor executor = new ThreadPoolExecutor(5, 5, 0, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>());
        for (int t = 0; t < 5; t++) {
            executor.execute(() -> {
                String threadName = Thread.currentThread().getName();
                for (int i = 0; i < 50; i++) {
                    String out = LocalDateTime.now() + " [" + threadName + "]";
                    if (rand.nextBoolean()) {
                        window.increment();
                        System.out.println(out + " +1");
                    }
                    try {
                        Thread.sleep(rand.nextInt(100));
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            });
        }

        //关闭线程池
        executor.shutdown();
        //等待线程池中所有线程执行完毕
        try {
            executor.awaitTermination(1, TimeUnit.MINUTES);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        //通知线程thread退出
        thread.interrupt();
    }

}

更多推荐