当一个线程start()之后,是在run方法里通过wait()、sleep()等方法来改变状态,而线程池是改不了线程的状态的,线程池的作用是用来管理这些线程何时开启start,还没开启的线程怎么排队,优先级是怎样的,线程池就是做这些工作。
下面来自定义一个线程池,首先定义一个接口,接口方法实现两个方法,加入Runnable对象和删除:
public interface IThreadPool {
void add(Runnable runnable);
void remove();
}
然后定义这个线程池:
public class ThreadPoolImpl implements IThreadPool{
private static int WORK_NUM = 2;//线程池内的工作线程数为2
private static PriorityBlockingQueue<Runnable> blockingQueue = new PriorityBlockingQueue<>();//线程队列
@Override
public void add(Runnable runnable) {
}
@Override
public void remove() {
}
}
首先实现IThreadPool接口,然后定义了一个固定线程(也就是该线程池里一直工作运行的线程)数量为2,还定义了一个权限队列(具有优先级PriorityBlockingQueue)blockingQueue 。接下来定义这个工作线程:
class ThreadPoolWorkerThread extends Thread{
private boolean isRunning = true;
@Override
public void run() {
while (isRunning) {
synchronized (ThreadPoolWorkerThread.class) {
try {
Runnable runnable = blockingQueue.take();
//取出线程后执行它的run逻辑
runnable.run();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
线程池里的工作线程是为了从队列里取出线程然后进行它们各自的run方法,而这个过程是需要同步,所以使用了synchronized锁(根据之前分析的锁机制可以根据实际情况来优化)。那什么时候来开启这些工作线程,当然是外部在构造线程池的时候开启这些工作线程,所以ThreadPoolImpl 的构造方法:
public ThreadPoolImpl() {
for (int i = 0; i < WORK_NUM; i++) {
ThreadPoolWorkerThread thread = new ThreadPoolWorkerThread();
thread.start();
}
}
当外部Activity构造ThreadPoolImpl对象的时候就构造出线程池内部两个工作线程然后让它们启动起来,别忘了线程池的添加线程方法:
@Override
public void add(Runnable runnable) {
//这里可以根据实际要求设置一个添加数据的限制
blockingQueue.add(runnable);
}
正如注释所说那样,如果实际需要线程池的队列数量有限制,可以在此之前判断一下然后才进行添加。基本上整个线程池的创建思路就是这些,另外一些优化和补充的功能和细节则要根据实际开发需求来定,最后外部Activity要使用该线程池则如下:
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
IThreadPool threadPool = new ThreadPoolImpl();
for (int i = 0; i < 10; i++) {
threadPool.add(new Task("线程" + i));
}
}
static class Task implements Runnable{
private String name;
public Task(String name) {
this.name = name;
}
@Override
public void run() {
}
}
}
代码不难,相信大家都能理解,在构造线程池的时候,就已经让它里面的工作线程启动,然后不断轮询队列里的线程,而队列里的线程则通过外部调用者来添加进去,删除线程的方法也是外部去操纵线程池的remove方法。另外有一点要说明一下,虽然在工作线程里不断轮询去从队列里取线程的时候会有阻塞(加了锁),但因为工作线程本身也是子线程,所以不会阻塞到主线程(UI线程)了
————————————————
版权声明:本文为CSDN博主「Pingred_hjh」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_39867049/article/details/127766734