1 /* 2 * Copyright (C) 2019 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.apksig.util; 18 19 import static java.util.concurrent.TimeUnit.MILLISECONDS; 20 21 import java.util.concurrent.ArrayBlockingQueue; 22 import java.util.concurrent.ExecutorService; 23 import java.util.concurrent.Phaser; 24 import java.util.concurrent.ThreadPoolExecutor; 25 26 public interface RunnablesExecutor { 27 static final RunnablesExecutor SINGLE_THREADED = p -> p.createRunnable().run(); 28 29 static final RunnablesExecutor MULTI_THREADED = new RunnablesExecutor() { 30 private final int PARALLELISM = Math.min(32, Runtime.getRuntime().availableProcessors()); 31 private final int QUEUE_SIZE = 4; 32 33 @Override 34 public void execute(RunnablesProvider provider) { 35 final ExecutorService mExecutor = 36 new ThreadPoolExecutor(PARALLELISM, PARALLELISM, 37 0L, MILLISECONDS, 38 new ArrayBlockingQueue<>(QUEUE_SIZE), 39 new ThreadPoolExecutor.CallerRunsPolicy()); 40 41 Phaser tasks = new Phaser(1); 42 43 for (int i = 0; i < PARALLELISM; ++i) { 44 Runnable task = () -> { 45 Runnable r = provider.createRunnable(); 46 r.run(); 47 tasks.arriveAndDeregister(); 48 }; 49 tasks.register(); 50 mExecutor.execute(task); 51 } 52 53 // Waiting for the tasks to complete. 54 tasks.arriveAndAwaitAdvance(); 55 56 mExecutor.shutdownNow(); 57 } 58 }; 59 execute(RunnablesProvider provider)60 void execute(RunnablesProvider provider); 61 } 62