├── EasyExecutor
├── .gitignore
├── consumer-rules.pro
├── src
│ └── main
│ │ ├── AndroidManifest.xml
│ │ └── java
│ │ └── com
│ │ └── yc
│ │ └── easyexecutor
│ │ ├── InterExecutorLog.java
│ │ ├── MyThreadFactory.java
│ │ ├── SafeHandler.java
│ │ ├── AbsTaskExecutor.java
│ │ ├── LifecycleRunnable.java
│ │ ├── TaskHandlerThread.java
│ │ ├── DefaultTaskExecutor.java
│ │ └── DelegateTaskExecutor.java
├── proguard-rules.pro
└── build.gradle
├── ThreadBusiness
├── .gitignore
├── src
│ └── main
│ │ ├── res
│ │ ├── values
│ │ │ ├── strings.xml
│ │ │ ├── colors.xml
│ │ │ └── styles.xml
│ │ ├── mipmap-hdpi
│ │ │ ├── ic_launcher.png
│ │ │ └── ic_launcher_round.png
│ │ ├── mipmap-mdpi
│ │ │ ├── ic_launcher.png
│ │ │ └── ic_launcher_round.png
│ │ ├── mipmap-xhdpi
│ │ │ ├── ic_launcher.png
│ │ │ └── ic_launcher_round.png
│ │ ├── mipmap-xxhdpi
│ │ │ ├── ic_launcher.png
│ │ │ └── ic_launcher_round.png
│ │ ├── mipmap-xxxhdpi
│ │ │ ├── ic_launcher.png
│ │ │ └── ic_launcher_round.png
│ │ ├── mipmap-anydpi-v26
│ │ │ ├── ic_launcher.xml
│ │ │ └── ic_launcher_round.xml
│ │ ├── layout
│ │ │ ├── activity_thread_main.xml
│ │ │ ├── activity_test.xml
│ │ │ ├── activity_easy_executor.xml
│ │ │ ├── activity_thread.xml
│ │ │ ├── activity_poll_thread.xml
│ │ │ └── activity_test_thread_count.xml
│ │ ├── drawable-v24
│ │ │ └── ic_launcher_foreground.xml
│ │ └── drawable
│ │ │ └── ic_launcher_background.xml
│ │ ├── java
│ │ └── com
│ │ │ └── yc
│ │ │ └── ycthreadpool
│ │ │ ├── LogCallback.java
│ │ │ ├── ThreadMainActivity.java
│ │ │ ├── App.java
│ │ │ ├── EasyExecutorActivity.java
│ │ │ ├── ExecutorsTestActivity.java
│ │ │ ├── ThreadPollActivity.java
│ │ │ ├── ThreadPoolExecutorActivity.java
│ │ │ └── ThreadActivity.java
│ │ └── AndroidManifest.xml
├── proguard-rules.pro
└── build.gradle
├── ThreadPoolLib
├── .gitignore
├── src
│ └── main
│ │ ├── res
│ │ └── values
│ │ │ └── strings.xml
│ │ ├── AndroidManifest.xml
│ │ └── java
│ │ └── com
│ │ └── yc
│ │ └── ycthreadpoollib
│ │ ├── config
│ │ ├── ThreadPoolType.java
│ │ └── ThreadConfigs.java
│ │ ├── builder
│ │ ├── IThreadPoolBuilder.java
│ │ ├── CachedBuilderImpl.java
│ │ ├── ScheduledBuilderImpl.java
│ │ ├── SingleBuilderImpl.java
│ │ ├── FixedBuilderImpl.java
│ │ ├── AbsThreadPoolBuilder.java
│ │ └── CustomBuilderImpl.java
│ │ ├── ScheduleTask.java
│ │ ├── callback
│ │ ├── AsyncCallback.java
│ │ ├── ThreadCallback.java
│ │ └── NormalCallback.java
│ │ ├── deliver
│ │ ├── JavaDeliver.java
│ │ └── AndroidDeliver.java
│ │ ├── factory
│ │ └── MyThreadFactory.java
│ │ ├── utils
│ │ ├── DelayTaskExecutor.java
│ │ └── ThreadToolUtils.java
│ │ └── wrapper
│ │ ├── CallableWrapper.java
│ │ └── RunnableWrapper.java
├── proguard-rules.pro
└── build.gradle
├── ThreadTaskLib
├── .gitignore
├── src
│ └── main
│ │ ├── res
│ │ └── values
│ │ │ └── strings.xml
│ │ ├── AndroidManifest.xml
│ │ └── java
│ │ └── com
│ │ └── yc
│ │ └── taskscheduler
│ │ ├── SchedulerTask.java
│ │ ├── MyThreadFactory.java
│ │ ├── AbsTaskRunnable.java
│ │ └── TaskScheduler.java
├── proguard-rules.pro
└── build.gradle
├── settings.gradle
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── .idea
├── caches
│ └── build_file_checksums.ser
├── encodings.xml
├── vcs.xml
├── compiler.xml
├── runConfigurations.xml
├── modules.xml
├── inspectionProfiles
│ └── Project_Default.xml
├── jarRepositories.xml
├── misc.xml
├── codeStyles
│ └── Project.xml
└── markdown-navigator.xml
├── read
├── 08.线程导致OOM.md
├── 07.设置线程池大小.md
├── 09.线程池一些思考.md
├── 06.设置线程池原理.md
├── 05.线程池复用原理.md
├── 03.线程池深入思考.md
└── 02.线程池案例测试.md
├── gradle.properties
├── .gitignore
├── yc.gradle
├── gradlew.bat
└── gradlew
/EasyExecutor/.gitignore:
--------------------------------------------------------------------------------
1 | /build
--------------------------------------------------------------------------------
/EasyExecutor/consumer-rules.pro:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ThreadBusiness/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/ThreadPoolLib/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/ThreadTaskLib/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':ThreadBusiness', ':ThreadPoolLib'
2 | include ':ThreadTaskLib'
3 | include ':EasyExecutor'
4 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yangchong211/YCThreadPool/HEAD/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/ThreadBusiness/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
5 | * @author yangchong 6 | * blog : https://github.com/yangchong211 7 | * time : 2019/05/17 8 | * desc : 枚举 9 | * revise: 10 | *11 | */ 12 | public enum ThreadPoolType { 13 | CACHED, 14 | FIXED, 15 | SCHEDULED, 16 | SINGLE, 17 | CUSTOM; 18 | 19 | private ThreadPoolType() { 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /ThreadPoolLib/src/main/java/com/yc/ycthreadpoollib/builder/IThreadPoolBuilder.java: -------------------------------------------------------------------------------- 1 | package com.yc.ycthreadpoollib.builder; 2 | 3 | import com.yc.ycthreadpoollib.config.ThreadPoolType; 4 | import com.yc.ycthreadpoollib.factory.MyThreadFactory; 5 | import com.yc.ycthreadpoollib.config.ThreadPoolType; 6 | 7 | import java.util.concurrent.ExecutorService; 8 | 9 | public interface IThreadPoolBuilder
8 | * @author yangchong 9 | * email : yangchong211@163.com 10 | * time : 2019/5/11 11 | * desc : ThreadFactory 12 | * revise : 13 | * GitHub : https://github.com/yangchong211/YCThreadPool 14 | *15 | */ 16 | public class MyThreadFactory implements ThreadFactory { 17 | 18 | private final AtomicLong mCount = new AtomicLong(0); 19 | private final String threadName; 20 | 21 | public MyThreadFactory(String threadName){ 22 | this.threadName = threadName; 23 | } 24 | 25 | @Override 26 | public Thread newThread(Runnable r) { 27 | return new Thread(r, threadName + mCount.getAndIncrement()); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Built application files 2 | *.apk 3 | *.ap_ 4 | 5 | # Files for the ART/Dalvik VM 6 | *.dex 7 | 8 | # Java class files 9 | *.class 10 | 11 | # Generated files 12 | bin/ 13 | gen/ 14 | out/ 15 | 16 | # Gradle files 17 | .gradle/ 18 | build/ 19 | 20 | # Local configuration file (sdk path, etc) 21 | local.properties 22 | 23 | # Proguard folder generated by Eclipse 24 | proguard/ 25 | 26 | # Log Files 27 | *.log 28 | 29 | # Android Studio Navigation editor temp files 30 | .navigation/ 31 | 32 | # Android Studio captures folder 33 | captures/ 34 | 35 | # Intellij 36 | *.iml 37 | .idea/workspace.xml 38 | .idea/tasks.xml 39 | .idea/gradle.xml 40 | .idea/dictionaries 41 | .idea/libraries 42 | 43 | # Keystore files 44 | *.jks 45 | 46 | # External native build folder generated in Android Studio 2.2 and later 47 | .externalNativeBuild 48 | 49 | # Google Services (e.g. APIs or Firebase) 50 | google-services.json 51 | 52 | # Freeline 53 | freeline.py 54 | freeline/ 55 | freeline_project_description.json 56 | .idea/ 57 | .gradle/ 58 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 |
10 | * @author: yangchong 11 | * blog : www.pedaily.cn 12 | * time : 2017/08/22 13 | * desc : 回调数据 14 | * revise: 15 | *16 | */ 17 | public class LogCallback implements ThreadCallback { 18 | 19 | private final String TAG = "LogCallback"; 20 | 21 | @Override 22 | public void onError(String name, Throwable t) { 23 | Log.e(TAG, "LogCallback"+"------onError"+"-----"+name+"----"+Thread.currentThread()+"----"+t.getMessage()); 24 | } 25 | 26 | @Override 27 | public void onCompleted(String name) { 28 | Log.e(TAG, "LogCallback"+"------onCompleted"+"-----"+name+"----"+Thread.currentThread()); 29 | } 30 | 31 | @Override 32 | public void onStart(String name) { 33 | Log.e(TAG, "LogCallback"+"------onStart"+"-----"+name+"----"+Thread.currentThread()); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /ThreadTaskLib/src/main/java/com/yc/taskscheduler/SchedulerTask.java: -------------------------------------------------------------------------------- 1 | package com.yc.taskscheduler; 2 | 3 | import java.util.concurrent.atomic.AtomicBoolean; 4 | 5 | 6 | public abstract class SchedulerTask implements Runnable { 7 | 8 | protected long startDelayMillisecond; 9 | protected long periodMillisecond; 10 | protected boolean mainThread = true; 11 | protected AtomicBoolean canceled = new AtomicBoolean(false); 12 | 13 | protected SchedulerTask(long periodMillisecond) { 14 | this.periodMillisecond = periodMillisecond; 15 | } 16 | 17 | protected SchedulerTask(long periodMillisecond,boolean mainThread) { 18 | this.periodMillisecond = periodMillisecond; 19 | this.mainThread = mainThread; 20 | } 21 | 22 | protected SchedulerTask(long periodMillisecond,boolean mainThread,long startDelayMillisecond) { 23 | this.periodMillisecond = periodMillisecond; 24 | this.mainThread = mainThread; 25 | this.startDelayMillisecond = startDelayMillisecond; 26 | } 27 | 28 | public abstract void onSchedule(); 29 | 30 | @Override 31 | public void run() { 32 | if(!canceled.get()) { 33 | onSchedule(); 34 | } 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /EasyExecutor/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'com.android.library' 3 | } 4 | apply from: rootProject.projectDir.absolutePath + "/yc.gradle" 5 | apply plugin: 'com.github.dcendents.android-maven' 6 | 7 | android { 8 | compileSdkVersion rootProject.ext.android["compileSdkVersion"] 9 | //buildToolsVersion rootProject.ext.android["buildToolsVersion"] 10 | defaultConfig { 11 | minSdkVersion rootProject.ext.android["minSdkVersion"] 12 | targetSdkVersion rootProject.ext.android["targetSdkVersion"] 13 | versionCode rootProject.ext.android["versionCode"] 14 | versionName rootProject.ext.android["versionName"] 15 | } 16 | 17 | buildTypes { 18 | release { 19 | minifyEnabled false 20 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 21 | } 22 | } 23 | compileOptions { 24 | sourceCompatibility JavaVersion.VERSION_1_8 25 | targetCompatibility JavaVersion.VERSION_1_8 26 | } 27 | } 28 | 29 | dependencies { 30 | implementation fileTree(dir: 'libs', include: ['*.jar']) 31 | implementation(rootProject.ext.dependencies["appcompat"]) 32 | implementation(rootProject.ext.dependencies["annotation"]) 33 | } -------------------------------------------------------------------------------- /ThreadPoolLib/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'com.android.library' 3 | } 4 | apply from: rootProject.projectDir.absolutePath + "/yc.gradle" 5 | apply plugin: 'com.github.dcendents.android-maven' 6 | 7 | android { 8 | compileSdkVersion rootProject.ext.android["compileSdkVersion"] 9 | //buildToolsVersion rootProject.ext.android["buildToolsVersion"] 10 | defaultConfig { 11 | minSdkVersion rootProject.ext.android["minSdkVersion"] 12 | targetSdkVersion rootProject.ext.android["targetSdkVersion"] 13 | versionCode rootProject.ext.android["versionCode"] 14 | versionName rootProject.ext.android["versionName"] 15 | } 16 | 17 | buildTypes { 18 | release { 19 | minifyEnabled false 20 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 21 | } 22 | } 23 | compileOptions { 24 | sourceCompatibility JavaVersion.VERSION_1_8 25 | targetCompatibility JavaVersion.VERSION_1_8 26 | } 27 | } 28 | 29 | dependencies { 30 | implementation fileTree(dir: 'libs', include: ['*.jar']) 31 | implementation(rootProject.ext.dependencies["appcompat"]) 32 | implementation(rootProject.ext.dependencies["annotation"]) 33 | } -------------------------------------------------------------------------------- /ThreadPoolLib/src/main/java/com/yc/ycthreadpoollib/ScheduleTask.java: -------------------------------------------------------------------------------- 1 | package com.yc.ycthreadpoollib; 2 | 3 | 4 | import androidx.annotation.NonNull; 5 | 6 | import java.util.concurrent.ExecutorService; 7 | import java.util.concurrent.Executors; 8 | import java.util.concurrent.ThreadFactory; 9 | 10 | public final class ScheduleTask { 11 | 12 | private final ExecutorService mExecutors; 13 | 14 | private ScheduleTask() { 15 | ThreadFactory threadFactory = new ThreadFactory() { 16 | @Override 17 | public Thread newThread(@NonNull Runnable runnable) { 18 | //创建一个线程 19 | return new Thread(runnable, "ScheduleTask"); 20 | } 21 | }; 22 | this.mExecutors = Executors.newSingleThreadExecutor(threadFactory); 23 | } 24 | 25 | public static ScheduleTask getInstance() { 26 | //单例模式 27 | return ScheduleTask.Holder.INSTANCE; 28 | } 29 | 30 | public void schedule(Runnable runnable) { 31 | //提交一个事务,runnable 32 | this.mExecutors.execute(runnable); 33 | } 34 | 35 | private static class Holder { 36 | 37 | private static final ScheduleTask INSTANCE = new ScheduleTask(); 38 | 39 | private Holder() { 40 | 41 | } 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /ThreadPoolLib/src/main/java/com/yc/ycthreadpoollib/builder/CachedBuilderImpl.java: -------------------------------------------------------------------------------- 1 | package com.yc.ycthreadpoollib.builder; 2 | 3 | import java.util.concurrent.ExecutorService; 4 | import java.util.concurrent.Executors; 5 | 6 | import com.yc.ycthreadpoollib.config.ThreadPoolType; 7 | import com.yc.ycthreadpoollib.factory.MyThreadFactory; 8 | 9 | /** 10 | *
11 | * @author yangchong 12 | * blog : https://github.com/yangchong211 13 | * time : 2019/05/17 14 | * desc : 缓存线程池 15 | * revise: 它是一个数量无限多的线程池,都是非核心线程,适合执行大量耗时小的任务 16 | *17 | */ 18 | public class CachedBuilderImpl extends AbsThreadPoolBuilder
12 | * @author yangchong 13 | * email : yangchong211@163.com 14 | * time : 2019/5/11 15 | * desc : 安全版本的handler 16 | * revise : 17 | * GitHub : https://github.com/yangchong211/YCThreadPool 18 | *19 | */ 20 | public final class SafeHandler extends Handler { 21 | 22 | private static final String TAG = "SafeHandler"; 23 | 24 | public SafeHandler(Looper looper) { 25 | super(looper); 26 | } 27 | 28 | public SafeHandler() { 29 | //默认是主线程 30 | super(Looper.getMainLooper()); 31 | } 32 | 33 | @Override 34 | public void dispatchMessage(@Nullable Message msg) { 35 | if (msg == null){ 36 | Log.d(TAG, "msg is null , return"); 37 | return; 38 | } 39 | try { 40 | super.dispatchMessage(msg); 41 | } catch (Exception e) { 42 | Log.d(TAG, "dispatchMessage Exception " + msg + " , " + e); 43 | } catch (Error error) { 44 | Log.d(TAG, "dispatchMessage error " + msg + " , " + error); 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /ThreadPoolLib/src/main/java/com/yc/ycthreadpoollib/builder/ScheduledBuilderImpl.java: -------------------------------------------------------------------------------- 1 | package com.yc.ycthreadpoollib.builder; 2 | 3 | import com.yc.ycthreadpoollib.config.ThreadPoolType; 4 | import com.yc.ycthreadpoollib.factory.MyThreadFactory; 5 | import com.yc.ycthreadpoollib.config.ThreadPoolType; 6 | 7 | import java.util.concurrent.ExecutorService; 8 | import java.util.concurrent.Executors; 9 | import java.util.concurrent.ScheduledExecutorService; 10 | 11 | /** 12 | *
13 | * @author yangchong 14 | * blog : https://github.com/yangchong211 15 | * time : 2019/05/17 16 | * desc : SingleBuilder 17 | * revise: 有数量固定的核心线程,且有数量无限多的非核心线程,适合用于执行定时任务和固定周期的重复任务 18 | *19 | */ 20 | public class ScheduledBuilderImpl extends AbsThreadPoolBuilder
12 | * @author yangchong 13 | * blog : https://github.com/yangchong211 14 | * time : 2019/05/17 15 | * desc : SingleBuilder 16 | * revise: 内部只有一个核心线程,所有任务进来都要排队按顺序执行 17 | *18 | */ 19 | public class SingleBuilderImpl extends AbsThreadPoolBuilder
22 | * @author yangchong 23 | * blog : https://github.com/yangchong211 24 | * time : 2017/08/22 25 | * desc : 异步callback回调接口 26 | * revise: 27 | *28 | */ 29 | public interface AsyncCallback
12 | * @author yangchong 13 | * blog : https://github.com/yangchong211 14 | * time : 2019/05/17 15 | * desc : SingleBuilder 16 | * revise: 线程数量固定的线程池,全部为核心线程,响应较快,不用担心线程会被回收。 17 | *18 | */ 19 | public class FixedBuilderImpl extends AbsThreadPoolBuilder
21 | * @author yangchong 22 | * blog : https://github.com/yangchong211 23 | * time : 24 | * desc : 一个回调接口,用于通知用户任务的状态回调委托类 25 | * 线程的名字可以自定义 26 | * revise: 27 | *28 | */ 29 | public interface ThreadCallback { 30 | 31 | /** 32 | * 当线程发生错误时,将调用此方法。 33 | * @param threadName 正在运行线程的名字 34 | * @param t 异常 35 | */ 36 | void onError(String threadName, Throwable t); 37 | 38 | /** 39 | * 通知用户知道它已经完成 40 | * @param threadName 正在运行线程的名字 41 | */ 42 | void onCompleted(String threadName); 43 | 44 | /** 45 | * 通知用户任务开始运行 46 | * @param threadName 正在运行线程的名字 47 | */ 48 | void onStart(String threadName); 49 | 50 | 51 | } 52 | -------------------------------------------------------------------------------- /.idea/inspectionProfiles/Project_Default.xml: -------------------------------------------------------------------------------- 1 |
26 | * @author yangchong 27 | * blog : https://github.com/yangchong211 28 | * time : 29 | * desc : 默认情况下,用于Java平台的交付。 30 | * revise: 31 | *32 | */ 33 | public final class JavaDeliver implements Executor { 34 | 35 | private static JavaDeliver instance = new JavaDeliver(); 36 | 37 | /** 38 | * 使用单利模式获取对象 39 | * @return JavaDeliver对象 40 | */ 41 | public static JavaDeliver getInstance() { 42 | return instance; 43 | } 44 | 45 | /** 46 | * 注意增加非空判断 47 | * @param runnable runnable 48 | */ 49 | @Override 50 | public void execute(@Nullable Runnable runnable) { 51 | if (runnable!=null){ 52 | runnable.run(); 53 | } 54 | } 55 | 56 | 57 | } 58 | -------------------------------------------------------------------------------- /ThreadBusiness/src/main/res/layout/activity_thread_main.xml: -------------------------------------------------------------------------------- 1 | 2 |
27 | * @author yangchong 28 | * blog : https://github.com/yangchong211 29 | * time : 2017/08/22 30 | * desc : 存储当前任务的某些配置 31 | * revise: 32 | *33 | */ 34 | 35 | public final class ThreadConfigs { 36 | 37 | /** 38 | * 线程的名称 39 | * 通过setName方法设置 40 | */ 41 | public String name; 42 | /** 43 | * 线程执行延迟的时间 44 | * 通过setDelay方法设置 45 | */ 46 | public long delay; 47 | /** 48 | * 线程执行者 49 | * JAVA或者ANDROID 50 | */ 51 | public Executor deliver; 52 | /** 53 | * 用户任务的状态回调callback 54 | */ 55 | public ThreadCallback callback; 56 | /** 57 | * 异步callback回调callback 58 | */ 59 | public AsyncCallback asyncCallback; 60 | 61 | } 62 | -------------------------------------------------------------------------------- /ThreadBusiness/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | apply from: rootProject.projectDir.absolutePath + "/yc.gradle" 3 | 4 | android { 5 | compileSdkVersion rootProject.ext.android["compileSdkVersion"] 6 | buildToolsVersion rootProject.ext.android["buildToolsVersion"] 7 | defaultConfig { 8 | applicationId "com.yc.ycthreadpool" 9 | minSdkVersion rootProject.ext.android["minSdkVersion"] 10 | targetSdkVersion rootProject.ext.android["targetSdkVersion"] 11 | versionCode rootProject.ext.android["versionCode"] 12 | versionName rootProject.ext.android["versionName"] 13 | } 14 | buildTypes { 15 | release { 16 | minifyEnabled false 17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 18 | } 19 | } 20 | compileOptions { 21 | sourceCompatibility JavaVersion.VERSION_1_8 22 | targetCompatibility JavaVersion.VERSION_1_8 23 | } 24 | } 25 | 26 | dependencies { 27 | implementation fileTree(include: ['*.jar'], dir: 'libs') 28 | implementation(rootProject.ext.dependencies["appcompat"]) 29 | implementation(rootProject.ext.dependencies["annotation"]) 30 | //通用日志输出库 31 | implementation 'com.github.yangchong211.YCCommonLib:AppLogLib:1.3.0' 32 | implementation 'com.github.yangchong211.YCDialog:ToastUtils:3.6.9' 33 | // implementation project(':ThreadPoolLib') 34 | // implementation project(':ThreadTaskLib') 35 | // implementation project(':EasyExecutor') 36 | implementation 'com.github.yangchong211.YCThreadPool:ThreadPoolLib:1.3.8' 37 | implementation 'com.github.yangchong211.YCThreadPool:ThreadTaskLib:1.3.8' 38 | implementation 'com.github.yangchong211.YCThreadPool:EasyExecutor:1.3.8' 39 | } 40 | -------------------------------------------------------------------------------- /ThreadTaskLib/src/main/java/com/yc/taskscheduler/MyThreadFactory.java: -------------------------------------------------------------------------------- 1 | package com.yc.taskscheduler; 2 | 3 | import android.os.Process; 4 | 5 | import java.util.concurrent.ThreadFactory; 6 | import java.util.concurrent.atomic.AtomicInteger; 7 | 8 | 9 | class MyThreadFactory { 10 | 11 | static final class BackgroundRunnable implements Runnable { 12 | private final Runnable runnable; 13 | 14 | BackgroundRunnable(Runnable runnable) { 15 | this.runnable = runnable; 16 | } 17 | 18 | @Override 19 | public void run() { 20 | Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); 21 | runnable.run(); 22 | } 23 | } 24 | 25 | static final ThreadFactory TASK_SCHEDULER_FACTORY = new ThreadFactory() { 26 | private final AtomicInteger mCount = new AtomicInteger(1); 27 | 28 | @Override 29 | public Thread newThread(Runnable r) { 30 | return new Thread(new BackgroundRunnable(r), "TaskScheduler #" + mCount.getAndIncrement()); 31 | } 32 | }; 33 | 34 | static final ThreadFactory TIME_OUT_THREAD_FACTORY = new ThreadFactory() { 35 | private final AtomicInteger mCount = new AtomicInteger(1); 36 | 37 | @Override 38 | public Thread newThread(Runnable r) { 39 | return new Thread(new BackgroundRunnable(r), "TaskScheduler timeoutThread #" + mCount.getAndIncrement()); 40 | } 41 | }; 42 | 43 | static final ThreadFactory SCHEDULER_THREAD_FACTORY = new ThreadFactory() { 44 | 45 | private final AtomicInteger mCount = new AtomicInteger(1); 46 | 47 | @Override 48 | public Thread newThread(Runnable r) { 49 | return new Thread(new BackgroundRunnable(r), "TaskScheduler scheduler #" + mCount.getAndIncrement()); 50 | } 51 | }; 52 | } 53 | -------------------------------------------------------------------------------- /ThreadPoolLib/src/main/java/com/yc/ycthreadpoollib/builder/AbsThreadPoolBuilder.java: -------------------------------------------------------------------------------- 1 | package com.yc.ycthreadpoollib.builder; 2 | 3 | 4 | import com.yc.ycthreadpoollib.factory.MyThreadFactory; 5 | 6 | import java.util.Map; 7 | import java.util.concurrent.ConcurrentHashMap; 8 | import java.util.concurrent.ExecutorService; 9 | 10 | /** 11 | *
12 | * @author yangchong 13 | * blog : https://github.com/yangchong211 14 | * time : 2019/05/17 15 | * desc : 抽象类 16 | * revise: 17 | *18 | */ 19 | public abstract class AbsThreadPoolBuilder
27 | * @author yangchong 28 | * blog : https://github.com/yangchong211 29 | * time : 2017/08/22 30 | * desc : 默认Thread工厂 31 | * revise: 32 | *33 | */ 34 | public class MyThreadFactory implements ThreadFactory { 35 | 36 | /** 37 | * ThreadFactory 38 | * ThreadFactory是一个接口,里面只有一个newThread方法 39 | * 线程工厂,为线程池提供新线程的创建 40 | */ 41 | 42 | private int priority; 43 | 44 | /** 45 | * 构造方法,默认为优先级是:Thread.NORM_PRIORITY 46 | */ 47 | public MyThreadFactory() { 48 | this.priority = Thread.NORM_PRIORITY; 49 | } 50 | 51 | /** 52 | * 构造方法 53 | * @param priority 优先级 54 | */ 55 | public MyThreadFactory(int priority) { 56 | this.priority = priority; 57 | } 58 | 59 | 60 | @Override 61 | public Thread newThread(@NonNull Runnable runnable) { 62 | // 创建线程 63 | Thread thread = new Thread(runnable); 64 | // 设置线程优先级 65 | thread.setPriority(priority); 66 | return thread; 67 | } 68 | 69 | } 70 | -------------------------------------------------------------------------------- /yc.gradle: -------------------------------------------------------------------------------- 1 | ext { 2 | 3 | android = [ 4 | compileSdkVersion: 29, 5 | buildToolsVersion: "29.0.0", 6 | minSdkVersion : 17, 7 | targetSdkVersion : 29, 8 | versionCode : 22, 9 | versionName : "1.8.2" //必须是int或者float,否则影响线上升级 10 | ] 11 | 12 | buildToolsVersion = "29.0.0" 13 | minSdkVersion = 17 14 | targetSdkVersion = 29 15 | compileSdkVersion = 29 16 | versionCode = 22 17 | versionName = "1.8.2" 18 | 19 | //AndroidX系列 20 | appcompatVersion = '1.2.0' 21 | annotationVersion = '1.2.0' 22 | cardviewVersion = '1.0.0' 23 | mediaVersion = '1.0.1' 24 | swiperefreshlayoutVersion = '1.0.0' 25 | materialVersion = '1.0.0-rc01' 26 | coordinatorlayoutVersion = '1.0.0' 27 | constraintlayoutVersion = '1.1.3' 28 | recyclerviewVersion = '1.0.0' 29 | multidexVersion = '1.0.2' 30 | 31 | dependencies = [ 32 | //AndroidX系列 33 | appcompat : "androidx.appcompat:appcompat:${appcompatVersion}", 34 | annotation : "androidx.annotation:annotation:${annotationVersion}", 35 | constraintlayout : "androidx.constraintlayout:constraintlayout:${constraintlayoutVersion}", 36 | coordinatorlayout : "androidx.coordinatorlayout:coordinatorlayout:${coordinatorlayoutVersion}", 37 | cardview : "androidx.cardview:cardview:${cardviewVersion}", 38 | recyclerview : "androidx.recyclerview:recyclerview:${recyclerviewVersion}", 39 | media : "androidx.media:media:${mediaVersion}", 40 | material : "com.google.android.material:material:${materialVersion}", 41 | swiperefreshlayout : "androidx.swiperefreshlayout:swiperefreshlayout:${swiperefreshlayoutVersion}", 42 | "multidex" : "com.android.support:multidex:$multidexVersion", 43 | ] 44 | 45 | } 46 | -------------------------------------------------------------------------------- /ThreadBusiness/src/main/res/drawable-v24/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 |
29 | * @author yangchong 30 | * blog : https://github.com/yangchong211 31 | * time : 2017/08/22 32 | * desc : 33 | * revise: 34 | *35 | */ 36 | public final class AndroidDeliver implements Executor { 37 | 38 | private static AndroidDeliver instance = new AndroidDeliver(); 39 | private Handler main = new Handler(Looper.getMainLooper()); 40 | 41 | public static AndroidDeliver getInstance() { 42 | return instance; 43 | } 44 | 45 | @Override 46 | public void execute(@Nullable final Runnable runnable) { 47 | //返回应用程序的looper,它位于应用程序的主线程中。 48 | Looper mainLooper = Looper.getMainLooper(); 49 | //如果当前looper就是当前主线程,那么调用run后不再执行下面的语句 50 | if (Looper.myLooper() == mainLooper && runnable!=null) { 51 | runnable.run(); 52 | return; 53 | } 54 | //开启子线程 55 | main.post(new Runnable() { 56 | @Override 57 | public void run() { 58 | //注意:这里需要增加非空判断 59 | if(runnable!=null){ 60 | runnable.run(); 61 | } 62 | } 63 | }); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /EasyExecutor/src/main/java/com/yc/easyexecutor/AbsTaskExecutor.java: -------------------------------------------------------------------------------- 1 | package com.yc.easyexecutor; 2 | 3 | import android.os.Handler; 4 | 5 | import androidx.annotation.NonNull; 6 | import androidx.annotation.RestrictTo; 7 | 8 | /** 9 | *
10 | * @author yangchong 11 | * email : yangchong211@163.com 12 | * time : 2019/5/11 13 | * desc : 抽象task任务类 14 | * revise : 15 | * GitHub : https://github.com/yangchong211/YCThreadPool 16 | *17 | */ 18 | public abstract class AbsTaskExecutor { 19 | 20 | /** 21 | * 核心任务的线程池,执行任务 22 | * 23 | * @param runnable 任务 24 | */ 25 | public abstract void executeOnCore(@NonNull Runnable runnable); 26 | 27 | /** 28 | * IO 密集型任务的线程池,执行任务 29 | * 30 | * @param runnable 任务 31 | */ 32 | public abstract void executeOnDiskIO(@NonNull Runnable runnable); 33 | 34 | /** 35 | * CPU 密集型任务的线程池,执行任务 36 | * 37 | * @param runnable 任务 38 | */ 39 | public abstract void executeOnCpu(@NonNull Runnable runnable); 40 | 41 | /** 42 | * UI主线程共有handler对象,执行任务 43 | * 44 | * @param runnable 任务 45 | */ 46 | public abstract void postToMainThread(@NonNull Runnable runnable); 47 | 48 | /** 49 | * 获取UI主线程共有handler对象 50 | * 51 | * @return handler对象 52 | */ 53 | public abstract Handler getMainHandler(); 54 | 55 | /** 56 | * 配合HandlerThread使用的handler【handlerThread具有自己的looper】,一般用来执行大量任务,执行任务 57 | * 一般用于在一个后台线程执行同一种任务,避免线程安全问题。如数据库,文件操作,轮训操作等 58 | * @param runnable 任务 59 | */ 60 | public abstract void postIoHandler(@NonNull Runnable runnable); 61 | 62 | /** 63 | * UI主线程共有handler对象,执行任务 64 | * 65 | * @param runnable 任务 66 | */ 67 | public void executeOnMainThread(@NonNull Runnable runnable) { 68 | if (isMainThread()) { 69 | runnable.run(); 70 | } else { 71 | postToMainThread(runnable); 72 | } 73 | } 74 | 75 | /** 76 | * 判断是否是主线程 77 | * 78 | * @return true 79 | */ 80 | public abstract boolean isMainThread(); 81 | } 82 | -------------------------------------------------------------------------------- /ThreadBusiness/src/main/java/com/yc/ycthreadpool/ThreadMainActivity.java: -------------------------------------------------------------------------------- 1 | package com.yc.ycthreadpool; 2 | 3 | import android.content.Intent; 4 | import android.os.Bundle; 5 | 6 | import androidx.appcompat.app.AppCompatActivity; 7 | 8 | import android.util.Log; 9 | import android.view.View; 10 | 11 | import com.yc.ycthreadpoollib.PoolThread; 12 | import com.yc.ycthreadpoollib.callback.AsyncCallback; 13 | import com.yc.ycthreadpoollib.callback.ThreadCallback; 14 | import com.yc.ycthreadpoollib.deliver.AndroidDeliver; 15 | 16 | import java.util.concurrent.Callable; 17 | import java.util.concurrent.ExecutionException; 18 | import java.util.concurrent.Future; 19 | import java.util.concurrent.TimeUnit; 20 | 21 | 22 | public class ThreadMainActivity extends AppCompatActivity implements View.OnClickListener { 23 | 24 | @Override 25 | protected void onCreate(Bundle savedInstanceState) { 26 | super.onCreate(savedInstanceState); 27 | setContentView(R.layout.activity_thread_main); 28 | findViewById(R.id.tv_easy).setOnClickListener(this); 29 | findViewById(R.id.tv_poll).setOnClickListener(this); 30 | findViewById(R.id.tv_executors).setOnClickListener(this); 31 | findViewById(R.id.tv_thread).setOnClickListener(this); 32 | 33 | 34 | // 计算可使用的最大内存 35 | final int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024); 36 | // 取四分之一的可用内存作为缓存 37 | final int cacheSize = maxMemory / 4; 38 | } 39 | 40 | @Override 41 | public void onClick(View v) { 42 | switch (v.getId()){ 43 | case R.id.tv_easy: 44 | EasyExecutorActivity.startActivity(this); 45 | break; 46 | case R.id.tv_poll: 47 | ThreadPollActivity.startActivity(this); 48 | break; 49 | case R.id.tv_executors: 50 | startActivity(new Intent(this, ExecutorsTestActivity.class)); 51 | break; 52 | case R.id.tv_thread: 53 | startActivity(new Intent(this,ThreadActivity.class)); 54 | break; 55 | default: 56 | break; 57 | } 58 | } 59 | 60 | } 61 | -------------------------------------------------------------------------------- /EasyExecutor/src/main/java/com/yc/easyexecutor/LifecycleRunnable.java: -------------------------------------------------------------------------------- 1 | package com.yc.easyexecutor; 2 | 3 | 4 | import android.os.Handler; 5 | 6 | import androidx.lifecycle.GenericLifecycleObserver; 7 | import androidx.lifecycle.Lifecycle; 8 | import androidx.lifecycle.LifecycleOwner; 9 | 10 | 11 | public class LifecycleRunnable implements Runnable { 12 | 13 | private Runnable mOriginRunnable; 14 | private LifecycleOwner mLifecycleOwner; 15 | private GenericLifecycleObserver mLifecycleObserver; 16 | 17 | 18 | LifecycleRunnable(LifecycleOwner lifecycleOwner, final Handler handler, 19 | final Lifecycle.Event targetEvent, 20 | final Runnable originRunnable) { 21 | if(originRunnable == null || lifecycleOwner == null) { 22 | return; 23 | } 24 | this.mLifecycleOwner = lifecycleOwner; 25 | this.mOriginRunnable = originRunnable; 26 | mLifecycleObserver = new GenericLifecycleObserver() { 27 | @Override 28 | public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) { 29 | if(event == targetEvent) { 30 | if(mLifecycleOwner!=null ) { 31 | mLifecycleOwner.getLifecycle().removeObserver(this); 32 | } 33 | handler.removeCallbacks(LifecycleRunnable.this); 34 | } 35 | } 36 | }; 37 | if(DelegateTaskExecutor.getInstance().isMainThread()) { 38 | mLifecycleOwner.getLifecycle().addObserver(mLifecycleObserver); 39 | }else { 40 | DelegateTaskExecutor.getInstance().postToMainThread(new Runnable() { 41 | @Override 42 | public void run() { 43 | mLifecycleOwner.getLifecycle().addObserver(mLifecycleObserver); 44 | } 45 | }); 46 | } 47 | } 48 | 49 | 50 | @Override 51 | public void run() { 52 | if(mOriginRunnable!=null && mLifecycleOwner!=null) { 53 | mOriginRunnable.run(); 54 | mLifecycleOwner.getLifecycle().removeObserver(mLifecycleObserver); 55 | } 56 | 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /EasyExecutor/src/main/java/com/yc/easyexecutor/TaskHandlerThread.java: -------------------------------------------------------------------------------- 1 | 2 | package com.yc.easyexecutor; 3 | 4 | import android.os.Handler; 5 | import android.os.HandlerThread; 6 | import android.os.Looper; 7 | 8 | import java.util.concurrent.ConcurrentHashMap; 9 | 10 | 11 | /** 12 | *
13 | * @author yangchong 14 | * email : yangchong211@163.com 15 | * time : 2019/5/11 16 | * desc : 抽象task任务类 17 | * revise : 18 | * GitHub : https://github.com/yangchong211/YCThreadPool 19 | *20 | */ 21 | public final class TaskHandlerThread extends HandlerThread { 22 | 23 | private static final ConcurrentHashMap
27 | * @author: yangchong 28 | * blog : https://github.com/yangchong211 29 | * time : 2017/08/22 30 | * desc : 使用核心线程池启动延迟任务的类 31 | * revise: 32 | *33 | */ 34 | @SuppressWarnings("ALL") 35 | public final class DelayTaskExecutor { 36 | 37 | private volatile ScheduledExecutorService dispatcher; 38 | 39 | /** 40 | * 单利模式,创建线程池对象 41 | */ 42 | private static DelayTaskExecutor instance = new DelayTaskExecutor(); 43 | 44 | private DelayTaskExecutor() { 45 | dispatcher = Executors.newScheduledThreadPool(1, new ThreadFactory() { 46 | @Override 47 | public Thread newThread(Runnable runnable) { 48 | Thread thread = new Thread(runnable); 49 | thread.setName("Yc_Delay-Task-Dispatcher"); 50 | thread.setPriority(Thread.MAX_PRIORITY); 51 | return thread; 52 | } 53 | }); 54 | } 55 | 56 | public static synchronized DelayTaskExecutor get() { 57 | return instance; 58 | } 59 | 60 | /** 61 | * 启动 62 | * @param delay 延迟执行的时间,注意默认单位是TimeUnit.MILLISECONDS 63 | * @param pool pool线程池 64 | * @param task runnable 65 | */ 66 | public void postDelay(long delay, final ExecutorService pool, final Runnable task) { 67 | if (delay == 0) { 68 | //如果时间是0,那么普通开启 69 | pool.execute(task); 70 | return; 71 | } 72 | 73 | //延时操作 74 | dispatcher.schedule(new Runnable() { 75 | @Override 76 | public void run() { 77 | //在将来的某个时间执行给定的命令。该命令可以在新线程、池线程或调用线程中执行 78 | pool.execute(task); 79 | } 80 | }, delay, TimeUnit.MILLISECONDS); 81 | } 82 | 83 | } 84 | -------------------------------------------------------------------------------- /ThreadPoolLib/src/main/java/com/yc/ycthreadpoollib/utils/ThreadToolUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2017 yangchong211(github.com/yangchong211) 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.yc.ycthreadpoollib.utils; 18 | 19 | 20 | import com.yc.ycthreadpoollib.callback.ThreadCallback; 21 | 22 | /** 23 | *
24 | * @author yangchong 25 | * blog : https://www.jianshu.com/p/53017c3fc75d 26 | * time : 2017/08/22 27 | * desc : 工具 28 | * revise: 29 | *30 | */ 31 | public final class ThreadToolUtils { 32 | 33 | /** 34 | * 标志:在android平台上 35 | */ 36 | private static boolean isAndroid; 37 | 38 | /* 39 | * 静态代码块 40 | * 判断是否是android环境 41 | * Class.forName(xxx.xx.xx) 返回的是一个类对象 42 | * 首先要明白在java里面任何class都要装载在虚拟机上才能运行。 43 | */ 44 | static { 45 | try { 46 | Class.forName("android.os.Build"); 47 | isAndroid = true; 48 | } catch (Exception e) { 49 | isAndroid = false; 50 | } 51 | } 52 | 53 | /** 54 | * 判断是否是Android 55 | * 56 | * @return true表示Android 57 | */ 58 | public static boolean isIsAndroid() { 59 | return isAndroid; 60 | } 61 | 62 | /** 63 | * 重置线程名并设置UnCaughtExceptionHandler包装回调,以便在发生异常时通知用户 64 | * 65 | * @param thread The thread who should be reset. 66 | * @param name non-null, thread name 67 | * @param callback a callback to notify user. 68 | */ 69 | public static void resetThread(Thread thread, final String name, final ThreadCallback callback) { 70 | //捕获单个线程的异常 71 | thread.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() { 72 | @Override 73 | public void uncaughtException(Thread t, Throwable e) { 74 | //如果线程出现了异常,则会回调该方法 75 | if (callback != null) { 76 | callback.onError(name, e); 77 | } 78 | } 79 | }); 80 | thread.setName(name); 81 | } 82 | 83 | public static void sleepThread(long time) { 84 | if (time <= 0) { 85 | return; 86 | } 87 | try { 88 | Thread.sleep(time); 89 | } catch (InterruptedException e) { 90 | throw new RuntimeException("Thread has been interrupted", e); 91 | } 92 | } 93 | 94 | } -------------------------------------------------------------------------------- /ThreadPoolLib/src/main/java/com/yc/ycthreadpoollib/wrapper/CallableWrapper.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2017 yangchong211(github.com/yangchong211) 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.yc.ycthreadpoollib.wrapper; 18 | 19 | 20 | import com.yc.ycthreadpoollib.config.ThreadConfigs; 21 | 22 | import java.util.concurrent.Callable; 23 | 24 | import com.yc.ycthreadpoollib.callback.NormalCallback; 25 | import com.yc.ycthreadpoollib.callback.ThreadCallback; 26 | import com.yc.ycthreadpoollib.utils.ThreadToolUtils; 27 | 28 | /** 29 | *
30 | * @author yangchong 31 | * blog : https://github.com/yangchong211 32 | * time : 2017/08/22 33 | * desc : CallableWrapper 34 | * revise: 35 | *36 | */ 37 | public final class CallableWrapper
29 | * @author yangchong 30 | * blog : https://github.com/yangchong211 31 | * time : 2017/08/22 32 | * desc : RunnableWrapper 33 | * revise: 34 | *35 | */ 36 | public final class RunnableWrapper implements Runnable { 37 | 38 | private String name; 39 | private NormalCallback normal; 40 | private Runnable runnable; 41 | private Callable callable; 42 | 43 | public RunnableWrapper(ThreadConfigs configs) { 44 | this.name = configs.name; 45 | this.normal = new NormalCallback(configs.callback, configs.deliver, configs.asyncCallback); 46 | } 47 | 48 | /** 49 | * 启动异步任务,普通的 50 | * @param runnable runnable 51 | * @return 对象 52 | */ 53 | public RunnableWrapper setRunnable(Runnable runnable) { 54 | this.runnable = runnable; 55 | return this; 56 | } 57 | 58 | /** 59 | * 异步任务,回调用于接收可调用任务的结果 60 | * @param callable callable 61 | * @return 对象 62 | */ 63 | public RunnableWrapper setCallable(Callable callable) { 64 | this.callable = callable; 65 | return this; 66 | } 67 | 68 | /** 69 | * 自定义xxRunnable继承Runnable,实现run方法 70 | * 详细可以看我的GitHub:https://github.com/yangchong211 71 | */ 72 | @Override 73 | public void run() { 74 | //获取线程 75 | Thread current = Thread.currentThread(); 76 | //重置线程 77 | ThreadToolUtils.resetThread(current, name, normal); 78 | //开始 79 | normal.onStart(name); 80 | //注意需要判断runnable,callable非空 81 | // avoid NullPointException 82 | if (runnable != null) { 83 | runnable.run(); 84 | } else if (callable != null) { 85 | try { 86 | Object result = callable.call(); 87 | //监听成功 88 | normal.onSuccess(result); 89 | } catch (Exception e) { 90 | //监听异常 91 | normal.onError(name, e); 92 | } 93 | } 94 | //监听完成 95 | normal.onCompleted(name); 96 | } 97 | 98 | 99 | } 100 | -------------------------------------------------------------------------------- /ThreadPoolLib/src/main/java/com/yc/ycthreadpoollib/builder/CustomBuilderImpl.java: -------------------------------------------------------------------------------- 1 | package com.yc.ycthreadpoollib.builder; 2 | 3 | import com.yc.ycthreadpoollib.config.ThreadPoolType; 4 | import com.yc.ycthreadpoollib.factory.MyThreadFactory; 5 | import com.yc.ycthreadpoollib.config.ThreadPoolType; 6 | 7 | import java.util.concurrent.BlockingQueue; 8 | import java.util.concurrent.ExecutorService; 9 | import java.util.concurrent.SynchronousQueue; 10 | import java.util.concurrent.ThreadPoolExecutor; 11 | import java.util.concurrent.TimeUnit; 12 | 13 | /** 14 | *
15 | * @author yangchong 16 | * blog : https://github.com/yangchong211 17 | * time : 2019/05/17 18 | * desc : 自定义线程池 19 | * revise: 这个是高级的用法,需要对线程池有较深入的理解才可以使用。否则建议直接使用系统提供api创建线程池 20 | *21 | */ 22 | public class CustomBuilderImpl extends AbsThreadPoolBuilder
23 | * @author yangchong 24 | * blog : https://github.com/yangchong211 25 | * time : 2017/08/22 26 | * desc : 回调委托类,监听 27 | * revise: 28 | *29 | */ 30 | public final class NormalCallback implements ThreadCallback, AsyncCallback { 31 | 32 | 33 | private ThreadCallback callback; 34 | private AsyncCallback async; 35 | private Executor deliver; 36 | 37 | public NormalCallback(ThreadCallback callback, Executor deliver, AsyncCallback async) { 38 | this.callback = callback; 39 | this.deliver = deliver; 40 | this.async = async; 41 | } 42 | 43 | /** 44 | * 回调成功 45 | * @param o 46 | */ 47 | @Override 48 | public void onSuccess(final Object o) { 49 | if (async == null) { 50 | return; 51 | } 52 | deliver.execute(new Runnable() { 53 | @Override 54 | public void run() { 55 | try { 56 | //noinspection unchecked 57 | async.onSuccess(o); 58 | } catch (Throwable t) { 59 | onFailed(t); 60 | } 61 | } 62 | }); 63 | } 64 | 65 | /** 66 | * 回调失败 67 | * @param t 异常 68 | */ 69 | @Override 70 | public void onFailed(final Throwable t) { 71 | if (async == null) { 72 | return; 73 | } 74 | deliver.execute(new Runnable() { 75 | @Override 76 | public void run() { 77 | async.onFailed(t); 78 | } 79 | }); 80 | } 81 | 82 | /** 83 | * 回调异常 84 | * @param name 线程name 85 | * @param t 异常 86 | */ 87 | @Override 88 | public void onError(final String name, final Throwable t) { 89 | onFailed(t); 90 | if (callback == null) { 91 | return; 92 | } 93 | deliver.execute(new Runnable() { 94 | @Override 95 | public void run() { 96 | callback.onError(name, t); 97 | } 98 | }); 99 | } 100 | 101 | /** 102 | * 回调完成 103 | * @param name 线程name 104 | */ 105 | @Override 106 | public void onCompleted(final String name) { 107 | if (callback == null) { 108 | return; 109 | } 110 | deliver.execute(new Runnable() { 111 | @Override 112 | public void run() { 113 | callback.onCompleted(name); 114 | } 115 | }); 116 | } 117 | 118 | /** 119 | * 回调开始 120 | * @param name 线程name 121 | */ 122 | @Override 123 | public void onStart(final String name) { 124 | if (callback == null) { 125 | return; 126 | } 127 | deliver.execute(new Runnable() { 128 | @Override 129 | public void run() { 130 | callback.onStart(name); 131 | } 132 | }); 133 | } 134 | } 135 | -------------------------------------------------------------------------------- /ThreadBusiness/src/main/java/com/yc/ycthreadpool/EasyExecutorActivity.java: -------------------------------------------------------------------------------- 1 | package com.yc.ycthreadpool; 2 | 3 | import android.content.Context; 4 | import android.content.Intent; 5 | import android.os.Bundle; 6 | import android.view.View; 7 | 8 | import androidx.annotation.Nullable; 9 | import androidx.appcompat.app.AppCompatActivity; 10 | 11 | import com.yc.apploglib.AppLogHelper; 12 | import com.yc.easyexecutor.DelegateTaskExecutor; 13 | import com.yc.toastutils.ToastUtils; 14 | 15 | 16 | public class EasyExecutorActivity extends AppCompatActivity implements View.OnClickListener { 17 | 18 | /** 19 | * 开启页面 20 | * 21 | * @param context 上下文 22 | */ 23 | public static void startActivity(Context context) { 24 | try { 25 | Intent target = new Intent(); 26 | target.setClass(context, EasyExecutorActivity.class); 27 | context.startActivity(target); 28 | } catch (Exception e){ 29 | e.printStackTrace(); 30 | } 31 | } 32 | 33 | @Override 34 | protected void onCreate(@Nullable Bundle savedInstanceState) { 35 | super.onCreate(savedInstanceState); 36 | setContentView(R.layout.activity_easy_executor); 37 | findViewById(R.id.tv_1).setOnClickListener(this); 38 | findViewById(R.id.tv_2).setOnClickListener(this); 39 | findViewById(R.id.tv_3).setOnClickListener(this); 40 | findViewById(R.id.tv_4).setOnClickListener(this); 41 | findViewById(R.id.tv_5).setOnClickListener(this); 42 | } 43 | 44 | @Override 45 | public void onClick(View v) { 46 | int id = v.getId(); 47 | if (id == R.id.tv_1){ 48 | test1(); 49 | } else if (id == R.id.tv_2){ 50 | test2(); 51 | } else if (id == R.id.tv_3){ 52 | test3(); 53 | } else if (id == R.id.tv_4){ 54 | test4(); 55 | } else if (id == R.id.tv_5){ 56 | test5(); 57 | } 58 | } 59 | 60 | private void test1() { 61 | DelegateTaskExecutor.getInstance().executeOnCore(new Runnable() { 62 | @Override 63 | public void run() { 64 | AppLogHelper.d("EasyExecutor: " , "核心任务的线程池,执行任务"); 65 | } 66 | }); 67 | } 68 | 69 | private void test2() { 70 | DelegateTaskExecutor.getInstance().executeOnDiskIO(new Runnable() { 71 | @Override 72 | public void run() { 73 | AppLogHelper.d("EasyExecutor: " , "IO 密集型任务的线程池,执行任务"); 74 | } 75 | }); 76 | } 77 | 78 | private void test3() { 79 | DelegateTaskExecutor.getInstance().executeOnCpu(new Runnable() { 80 | @Override 81 | public void run() { 82 | AppLogHelper.d("EasyExecutor: " , "CPU 密集型任务的线程池,执行任务"); 83 | } 84 | }); 85 | } 86 | 87 | private void test4() { 88 | DelegateTaskExecutor.getInstance().postToMainThread(new Runnable() { 89 | @Override 90 | public void run() { 91 | AppLogHelper.d("EasyExecutor: " , "UI主线程共有handler对象,执行任务1"); 92 | ToastUtils.showRoundRectToast("UI主线程共有handler对象"); 93 | } 94 | }); 95 | DelegateTaskExecutor.getInstance().executeOnMainThread(new Runnable() { 96 | @Override 97 | public void run() { 98 | AppLogHelper.d("EasyExecutor: " , "UI主线程共有handler对象,执行任务2"); 99 | ToastUtils.showRoundRectToast("UI主线程共有handler对象"); 100 | } 101 | }); 102 | } 103 | 104 | private void test5() { 105 | DelegateTaskExecutor.getInstance().postIoHandler(new Runnable() { 106 | @Override 107 | public void run() { 108 | AppLogHelper.d("EasyExecutor: " , "配合HandlerThread使用的handler,执行任务"); 109 | } 110 | }); 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /.idea/markdown-navigator.xml: -------------------------------------------------------------------------------- 1 | 2 |
20 | * @author yangchong 21 | * email : yangchong211@163.com 22 | * time : 2019/5/11 23 | * desc : task具体实现类 24 | * revise : 25 | * GitHub : https://github.com/yangchong211/YCThreadPool 26 | *27 | */ 28 | public class DefaultTaskExecutor extends AbsTaskExecutor { 29 | 30 | private final Object mLock = new Object(); 31 | /** 32 | * UI主线程共有handler对象 33 | */ 34 | @Nullable 35 | private volatile Handler mMainHandler; 36 | /** 37 | * 配合handlerThread使用的handler,一般用来执行大量任务 38 | */ 39 | @Nullable 40 | private volatile Handler mIoHandler; 41 | /** 42 | * 核心任务的线程池 43 | */ 44 | private final ExecutorService mCoreExecutor; 45 | /** 46 | * IO 密集型任务的线程池 47 | */ 48 | private final ExecutorService mDiskIO; 49 | /** 50 | * CPU 密集型任务的线程池 51 | */ 52 | private final ThreadPoolExecutor mCPUThreadPoolExecutor; 53 | /** 54 | * CPU 核数 55 | */ 56 | private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors(); 57 | /** 58 | * 线程池线程数 59 | */ 60 | private static final int CORE_POOL_SIZE = Math.max(2, Math.min(CPU_COUNT - 1, 5)); 61 | /** 62 | * 线程池线程数的最大值 63 | */ 64 | private static final int MAXIMUM_POOL_SIZE = CORE_POOL_SIZE; 65 | /** 66 | * 线程空置回收时间 67 | */ 68 | private static final int KEEP_ALIVE_SECONDS = 5; 69 | /** 70 | * 线程池队列 71 | */ 72 | private final BlockingQueue
14 | * @author yangchong 15 | * email : yangchong211@163.com 16 | * time : 2019/5/11 17 | * desc : task代理类,简单xia。具体用这个 18 | * revise : 19 | * GitHub : https://github.com/yangchong211/YCThreadPool 20 | *21 | */ 22 | public class DelegateTaskExecutor extends AbsTaskExecutor { 23 | 24 | private static volatile DelegateTaskExecutor sInstance; 25 | 26 | @NonNull 27 | private AbsTaskExecutor mDelegate; 28 | 29 | @NonNull 30 | private final AbsTaskExecutor mDefaultTaskExecutor; 31 | 32 | @NonNull 33 | private static final Executor sMainThreadExecutor = new Executor() { 34 | @Override 35 | public void execute(Runnable command) { 36 | if (command != null) { 37 | getInstance().postToMainThread(command); 38 | } 39 | } 40 | }; 41 | 42 | @NonNull 43 | private static final Executor sCoreThreadExecutor = new Executor() { 44 | @Override 45 | public void execute(Runnable command) { 46 | if (command != null) { 47 | getInstance().executeOnCore(command); 48 | } 49 | } 50 | }; 51 | 52 | @NonNull 53 | private static final Executor sIOThreadExecutor = new Executor() { 54 | @Override 55 | public void execute(Runnable command) { 56 | if (command != null) { 57 | getInstance().executeOnDiskIO(command); 58 | } 59 | } 60 | }; 61 | 62 | @NonNull 63 | private static final Executor sCpuThreadExecutor = new Executor() { 64 | @Override 65 | public void execute(Runnable command) { 66 | if (command != null) { 67 | getInstance().executeOnCpu(command); 68 | } 69 | } 70 | }; 71 | 72 | private DelegateTaskExecutor() { 73 | mDefaultTaskExecutor = new DefaultTaskExecutor(); 74 | mDelegate = mDefaultTaskExecutor; 75 | } 76 | 77 | @NonNull 78 | public static DelegateTaskExecutor getInstance() { 79 | if (sInstance != null) { 80 | return sInstance; 81 | } 82 | synchronized (DelegateTaskExecutor.class) { 83 | if (sInstance == null) { 84 | sInstance = new DelegateTaskExecutor(); 85 | } 86 | } 87 | return sInstance; 88 | } 89 | 90 | public void setDelegate(@Nullable AbsTaskExecutor taskExecutor) { 91 | mDelegate = taskExecutor == null ? mDefaultTaskExecutor : taskExecutor; 92 | } 93 | 94 | @Override 95 | public void executeOnCore(@NonNull Runnable runnable) { 96 | if (runnable != null) { 97 | mDelegate.executeOnCore(runnable); 98 | } 99 | } 100 | 101 | @Override 102 | public void executeOnDiskIO(@Nullable Runnable runnable) { 103 | if (runnable != null) { 104 | mDelegate.executeOnDiskIO(runnable); 105 | } 106 | } 107 | 108 | @Override 109 | public void executeOnCpu(@NonNull Runnable runnable) { 110 | if (runnable != null) { 111 | mDelegate.executeOnCpu(runnable); 112 | } 113 | } 114 | 115 | @Override 116 | public void postToMainThread(@Nullable Runnable runnable) { 117 | if (runnable != null) { 118 | mDelegate.postToMainThread(runnable); 119 | } 120 | } 121 | 122 | @Override 123 | public Handler getMainHandler() { 124 | return mDelegate.getMainHandler(); 125 | } 126 | 127 | @Override 128 | public void postIoHandler(@NonNull Runnable runnable) { 129 | if (runnable != null) { 130 | mDelegate.postIoHandler(runnable); 131 | } 132 | } 133 | 134 | @Override 135 | public void executeOnMainThread(@NonNull Runnable runnable) { 136 | super.executeOnMainThread(runnable); 137 | } 138 | 139 | /** 140 | * 使用HandlerThread和handler处理消息 141 | * 142 | * @return MainThreadExecutor 143 | */ 144 | @NonNull 145 | public Executor getMainThreadExecutor() { 146 | return sMainThreadExecutor; 147 | } 148 | 149 | /** 150 | * 获取核心线程池,主要是执行一些核心任务,比如初始化相关操作 151 | * 152 | * @return CoreThreadExecutor 153 | */ 154 | @NonNull 155 | public Executor getCoreThreadExecutor() { 156 | return sCoreThreadExecutor; 157 | } 158 | 159 | /** 160 | * 获得io密集型线程池,有好多任务其实占用的CPU time非常少,所以使用缓存线程池,基本上来着不拒 161 | * 162 | * @return IOThreadPoolExecutor 163 | */ 164 | @NonNull 165 | public Executor getIOThreadExecutor() { 166 | return sIOThreadExecutor; 167 | } 168 | 169 | /** 170 | * 获得cpu密集型线程池,因为占据CPU的时间片过多的话会影响性能,所以这里控制了最大并发,防止主线程的时间片减少 171 | * 172 | * @return CPUThreadPoolExecutor 173 | */ 174 | @NonNull 175 | public Executor getCpuThreadExecutor() { 176 | return sCpuThreadExecutor; 177 | } 178 | 179 | /** 180 | * 判断是否是主线程 181 | * 182 | * @return true表示主线成 183 | */ 184 | @Override 185 | public boolean isMainThread() { 186 | return mDelegate.isMainThread(); 187 | } 188 | 189 | 190 | /** 191 | * 执行有生命周期的任务 192 | */ 193 | public Runnable postToMainThread(LifecycleOwner lifecycleOwner, Runnable runnable) { 194 | LifecycleRunnable lifecycleRunnableDelegate = new LifecycleRunnable(lifecycleOwner, 195 | getMainHandler(), Lifecycle.Event.ON_DESTROY,runnable); 196 | mDelegate.postToMainThread(lifecycleRunnableDelegate); 197 | return lifecycleRunnableDelegate; 198 | } 199 | 200 | 201 | /** 202 | * 执行有生命周期的任务,指定Lifecycle.Event 203 | */ 204 | public Runnable postToMainThread(LifecycleOwner lifecycleOwner, 205 | Lifecycle.Event targetEvent, 206 | Runnable runnable) { 207 | LifecycleRunnable lifecycleRunnableDelegate = new LifecycleRunnable(lifecycleOwner, 208 | getMainHandler(),targetEvent,runnable); 209 | mDelegate.postToMainThread(lifecycleRunnableDelegate); 210 | return lifecycleRunnableDelegate; 211 | } 212 | 213 | 214 | public void postToMainThread(Runnable runnable,long delayed) { 215 | getMainHandler().postDelayed(runnable,delayed); 216 | } 217 | 218 | public Runnable postToMainThread(LifecycleOwner lifecycleOwner,Runnable runnable,long delayed) { 219 | LifecycleRunnable lifecycleRunnableDelegate = new LifecycleRunnable(lifecycleOwner, 220 | getMainHandler(),Lifecycle.Event.ON_DESTROY,runnable); 221 | getMainHandler().postDelayed(lifecycleRunnableDelegate,delayed); 222 | return lifecycleRunnableDelegate; 223 | } 224 | 225 | public void removeUICallback(Runnable runnable) { 226 | getMainHandler().removeCallbacks(runnable); 227 | } 228 | 229 | } 230 | -------------------------------------------------------------------------------- /read/03.线程池深入思考.md: -------------------------------------------------------------------------------- 1 | #### 目录介绍 2 | - 01.先看问题思考 3 | - 02.典型回答 4 | - 03.考点分析说明 5 | - 04.知识拓展 6 | - 05.线程池状态 7 | - 06.线程池实践 8 | - 07.线程池大小选择策略 9 | 10 | 11 | 12 | ### 01.先看问题思考 13 | - 线程是不能够重复启动的,创建或销毁线程存在一定的开销,所以利用线程池技术来提高系统资源利用效率,并简化线程管理,已经是非常成熟的选择。 14 | - 今天我要问你的问题是,Java 并发类库提供的线程池有哪几种? 分别有什么特点? 15 | 16 | 17 | ### 02.典型回答 18 | - 通常开发者都是利用 Executors 提供的通用线程池创建方法,去创建不同配置的线程池,主要区别在于不同的 ExecutorService 类型或者不同的初始参数。Executors 目前提供了 5 种不同的线程池创建配置: 19 | - newCachedThreadPool(),它是一种用来处理大量短时间工作任务的线程池,具有几个鲜明特点:它会试图缓存线程并重用,当无缓存线程可用时,就会创建新的工作线程;如果线程闲置的时间超过 60 秒,则被终止并移出缓存;长时间闲置时,这种线程池,不会消耗什么资源。其内部使用 SynchronousQueue 作为工作队列。 20 | - newFixedThreadPool(int nThreads),重用指定数目(nThreads)的线程,其背后使用的是无界的工作队列,任何时候最多有 nThreads 个工作线程是活动的。这意味着,如果任务数量超过了活动队列数目,将在工作队列中等待空闲线程出现;如果有工作线程退出,将会有新的工作线程被创建,以补足指定的数目 nThreads。 21 | - newSingleThreadExecutor(),它的特点在于工作线程数目被限制为 1,操作一个无界的工作队列,所以它保证了所有任务的都是被顺序执行,最多会有一个任务处于活动状态,并且不允许使用者改动线程池实例,因此可以避免其改变线程数目。 22 | - newSingleThreadScheduledExecutor() 和 newScheduledThreadPool(int corePoolSize),创建的是个 ScheduledExecutorService,可以进行定时或周期性的工作调度,区别在于单一工作线程还是多个工作线程。 23 | - newWorkStealingPool(int parallelism),这是一个经常被人忽略的线程池,Java 8 才加入这个创建方法,其内部会构建ForkJoinPool,利用Work-Stealing算法,并行地处理任务,不保证处理顺序。 24 | 25 | 26 | ### 03.考点分析说明 27 | - Java 并发包中的 Executor 框架无疑是并发编程中的重点,今天的题目考察的是对几种标准线程池的了解,我提供的是一个针对最常见的应用方式的回答。 28 | - 在大多数应用场景下,使用 Executors 提供的 5 个静态工厂方法就足够了,但是仍然可能需要直接利用 ThreadPoolExecutor 等构造函数创建,这就要求你对线程构造方式有进一步的了解,你需要明白线程池的设计和结构。 29 | - 另外,线程池这个定义就是个容易让人误解的术语,因为 ExecutorService 除了通常意义上“池”的功能,还提供了更全面的线程管理、任务提交等方法。 30 | - Executor 框架可不仅仅是线程池,我觉得至少下面几点值得深入学习: 31 | - 掌握 Executor 框架的主要内容,至少要了解组成与职责,掌握基本开发用例中的使用。 32 | - 对线程池和相关并发工具类型的理解,甚至是源码层面的掌握。 33 | - 实践中有哪些常见问题,基本的诊断思路是怎样的。 34 | - 如何根据自身应用特点合理使用线程池。 35 | 36 | 37 | ### 04.知识拓展 38 | - 首先,我们来看看 Executor 框架的基本组成,请参考下面的类图。 39 | -  40 | - 我们从整体上把握一下各个类型的主要设计目的: 41 | - Executor 是一个基础的接口,其初衷是将任务提交和任务执行细节解耦,这一点可以体会其定义的唯一方法。 42 | ``` 43 | void execute(Runnable command); 44 | ``` 45 | - Executor 的设计是源于 Java 早期线程 API 使用的教训,开发者在实现应用逻辑时,被太多线程创建、调度等不相关细节所打扰。就像我们进行 HTTP 通信,如果还需要自己操作 TCP 握手,开发效率低下,质量也难以保证。 46 | - ExecutorService 则更加完善,不仅提供 service 的管理功能,比如 shutdown 等方法,也提供了更加全面的提交任务机制,如返回Future而不是 void 的 submit 方法。 47 | ``` 48 |