是否可以在不破坏逻辑的情况下减少行数?

Is it possible to reduce the number of lines without breaking the logic?

我需要进行测试 - 哪个列表更快。为此,我 运行 每个测试都在一个新线程中进行。我在单独的 class 中为每个线程创建 运行nable 方法。我得到一个相当单调的代码,这是一个 DRY 违规行为。也许有人知道我如何可以同时 运行 所有线程而不破坏 DRY?

public class ThreadsManager {

    public static boolean stopThreads = false; //We change this variable MainActivity
    public static long timeOfStartTest = 0;

    public void startCollThreads() {
        stopThreads = false;
        timeOfStartTest = new Date().getTime();
        CollRunnable collRunnable = new CollRunnable();

        new Thread(collRunnable.addBeg(new ArrayList())).start();
        new Thread(collRunnable.addBeg(new LinkedList())).start();
        new Thread(collRunnable.addBeg(new CopyOnWriteArrayList())).start();

        new Thread(collRunnable.addMid(new ArrayList())).start();
        new Thread(collRunnable.addMid(new LinkedList())).start();
        new Thread(collRunnable.addMid(new CopyOnWriteArrayList())).start();

        new Thread(collRunnable.addEnd(new ArrayList())).start();
        new Thread(collRunnable.addEnd(new LinkedList())).start();
        new Thread(collRunnable.addEnd(new CopyOnWriteArrayList())).start();

        new Thread(collRunnable.search(new ArrayList())).start();
        new Thread(collRunnable.search(new LinkedList())).start();
        new Thread(collRunnable.search(new CopyOnWriteArrayList())).start();

        new Thread(collRunnable.removeBeg(new ArrayList())).start();
        new Thread(collRunnable.removeBeg(new LinkedList())).start();
        new Thread(collRunnable.removeBeg(new CopyOnWriteArrayList())).start();

        new Thread(collRunnable.removeMid(new ArrayList())).start();
        new Thread(collRunnable.removeMid(new LinkedList())).start();
        new Thread(collRunnable.removeMid(new CopyOnWriteArrayList())).start();

        new Thread(collRunnable.removeEnd(new ArrayList())).start();
        new Thread(collRunnable.removeEnd(new LinkedList())).start();
        new Thread(collRunnable.removeEnd(new CopyOnWriteArrayList())).start();
    }
}
public class CollRunnable {

    //region Adding in the beginning
    public Runnable addBeg(List list) {
        return () -> {
            for (int i = 0; i <= elementsNumber; i += 1) {
                if (stopThreads) {
                    return;
                }
                list.add(0, "");
            }
            updateViewModelValue(1,"Adding \nin the beginning", list);
        };
    }
    //endregion

    //region Adding in the middle
    public Runnable addMid(List list) {
        return () -> {
            for (int i = 0; i <= elementsNumber; i += 1) {
                if (stopThreads) {
                    return;
                }
                list.add(0, "");
            }
            updateViewModelValue(2, "Adding \nin the middle", list);
        };
    }
    //endregion

    //region Adding in the end
    public Runnable addEnd(List list) {
        return () -> {
            for (int i = 0; i <= elementsNumber; i += 1) {
                if (stopThreads) {
                    return;
                }
                list.add("");
            }
            updateViewModelValue(3, "Adding \nin the end", list);
        };
    }
    //endregion

    //region Search
    public Runnable search(List list) {
        return () -> {
            list.add(0);

            for (int i = 0; i <= elementsNumber; i += 1) {
                if (stopThreads) {
                    return;
                }
                list.get(0);
            }
            updateViewModelValue(4, "Search \nby value", list);
        };
    }
    //endregion

    //region Removing in the beginning
    public Runnable removeBeg(List list) {
        return () -> {
            for (int i = 0; i <= elementsNumber; i += 1) {
                if (stopThreads) {
                    return;
                }
                list.add("");
                list.remove("");
            }
            updateViewModelValue(5, "Removing \nin the beginning", list);
        };
    }
    //endregion

    //region Removing in the middle
    public Runnable removeMid(List list) {
        return () -> {
            for (int i = 0; i <= elementsNumber; i += 1) {
                if (stopThreads) {
                    return;
                }
                list.add("");
                list.remove("");
            }
            updateViewModelValue(6, "Removing \nin the middle", list);
        };
    }
    //endregion

    //region removing in the end
    public Runnable removeEnd(List list) {
        return () -> {
            for (int i = 0; i <= elementsNumber; i += 1) {
                if (stopThreads) {
                    return;
                }
                list.add("");
                list.remove("");
            }
            updateViewModelValue(7, "Removing \nin the end", list);
        };
    }
    //endregion

    private void updateViewModelValue(int numberOfTest, String testName, List list) {
        new Handler(Looper.getMainLooper()).post(() -> {
            DataClass dataClass = new DataClass(numberOfTest,testName, list, new Date().getTime() - timeOfStartTest);
            getCollInstance().viewModel.testResult.setValue(dataClass);
        });
    }
}

一种方法是分离列表的创建。例如在界面的帮助下:

@FunctionalInterface
public interface ListFactory {
    List create();
}

    // In ThreadsManager
    public void orquestate() {
        startCollThreads(() -> new ArrayList());
        startCollThreads(() -> new LinkedList());
        startCollThreads(() -> new CopyOnWriteArrayList());
    }

    private void startCollThreads(ListFactory listFactory) {
        stopThreads = false;
        timeOfStartTest = new Date().getTime();
        CollRunnable collRunnable = new CollRunnable();

        new Thread(collRunnable.addBeg(listFactory.create())).start();
        new Thread(collRunnable.addMid(listFactory.create())).start();
        // Other steps
    }

这与列表类型首先开始的步骤不完全相同,但我不知道这对您是否重要。

您可以利用 Supplier 功能界面。如下所示,提取一个方法,该方法将测试作为参数传递给列表类型的给定 函数

private void run_test(Function<List, Runnable> collRunnable) {
    new Thread(collRunnable.apply(new ArrayList())).start();
    new Thread(collRunnable.apply(new LinkedList())).start();
    new Thread(collRunnable.apply(new CopyOnWriteArrayList())).start();
}

然后调整您的 startCollThreads 方法:

public void startCollThreads() {
    stopThreads = false;
    timeOfStartTest = new Date().getTime();
    CollRunnable collRunnable = new CollRunnable();

    run_test(collRunnable::addBeg);
    run_test(collRunnable::addMid);
    run_test(collRunnable::addEnd);
    run_test(collRunnable::search);
    run_test(collRunnable::removeBeg);
    run_test(collRunnable::removeMid);
    run_test(collRunnable::removeEnd);
}

旁注

您正在使用 Raw 类型,您应该避免这种情况,see this source to see why

您还可以通过参数化作为参数传递的列表来使其更通用:

private void run_test(Function<List, Runnable> collRunnable, Supplier<List>... lists) {
    for (Supplier<List> list : lists) {
        new Thread(collRunnable.apply(list.get())).start();
    }
}

然后你可以调用不同列表的方法:

run_test(collRunnable::addBeg, ArrayList::new, LinkedList::new, CopyOnWriteArrayList::new);

run_test(collRunnable::addBeg, ArrayList::new);

您可以为此建议使用线程池 API。例如ExecutorService.html.invokeAll

例如:

   try {
       Runnable routine = (List<?> args) -> { // add your thread routine implementation }
       // you can use same routine for all tasks, or make any combination such as 3 different routines in list etc
       Runnable[] allTasks = new Runnable[8];
       Arrays.fill(allTasks, routine);
       ExecutorService pool =  Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
       // invoke all tasks from array in thread pool
       pool.invokeAll( Arrays.asList(allTasks) );
       // stop pool and await for it termination
       pool.shutdown();
       if (!pool.awaitTermination(60, TimeUnit.MINUTES)) {
         pool.shutdownNow();
       }
     }
   } catch (InterruptedException ie) {
     pool.shutdownNow();
     Thread.currentThread().interrupt();
   }