自己定义开发线程池
首先要明白线程池的作用,根本作用是维持一定的线程数去执行任务(也会是run方法) 弄明白这一点我们就可以写一个简易的线程池了
首先定义自己的线程池接口 ;
package com.MyThread.Mytest; import java.util.List; public interface MyIThreadPool { //执行任务 在执行任务时请确保任务添加完毕; public void execute(); //添加批量任务 public void addTask(List<Runnable> tasks); public void addTask(Runnable task); public void addTask(Runnable[] tasks);
//中途添加任务 当线程池开启时可以用该方法添加一般不介意使用
// 个人觉得线程池可以根据线程大小 维护 多个任务队列
//每个线程池取模 到对应任务队列中获取;当人本线程中没有提供此实现
public void addSafeTask(List<Runnable> tasks);
//销毁线程池 建议使用 销毁前会等待任务完成 public void destory(); //暴露销毁 不建议使用 可能任务没完成就直接退出 public void froceDestory(); } //接着已经开头提到的思想写出自己的简易线程池 ,具体代码如下 package com.MyThread.Mytest; import java.util.LinkedList; import java.util.List; public class MyIThreadPoolImp implements MyIThreadPool { //任务队列 private List<Runnable> taskqueue = new LinkedList<Runnable>(); //默认开启线程数量 private static final int defaultNums = 5; private int threadNums; //需设置为volatile型,当赋值变化时线程能感知 private volatile boolean isRunning = true; //线程数 不会变 不需要维持线程安全 Thread[] taskThreads; private MyIThreadPoolImp() { this(5); } private MyIThreadPoolImp(int num) { if (num <= 0) { threadNums = defaultNums; } else { threadNums = num; } taskThreads = new Thread[threadNums]; for (int i = 0; i < threadNums; i++) { Thread thread = new TaskThread(); thread.setName("TaskThread--" + i); taskThreads[i] = thread; } } public static MyIThreadPool getMyIThreadPool(int num) { return new MyIThreadPoolImp(num); } @Override public void addSafeTask(List<Runnable> tasks) { synchronized (taskqueue) { taskqueue.addAll(tasks); } } //执行任务 @Override public void execute() { for (int i = 0; i < threadNums; i++) { System.out.println(taskThreads[i].getName()+"开启啦"); taskThreads[i].start(); } } @Override public void addTask(Runnable[] tasks) { for (Runnable task : tasks) { taskqueue.add(task); } } @Override public void addTask(Runnable task) { taskqueue.add(task); } //批量添加任务 @Override public void addTask(List<Runnable> tasks) { taskqueue.addAll(tasks); } @Override public void destory() { while (!taskqueue.isEmpty()) { try { Thread.sleep(20); } catch (Exception e) { System.out.println("请等待任务完成"); e.printStackTrace(); } } isRunning = false; for (int i = 0; i < threadNums; i++) { taskThreads[i] = null; } } @Override public void froceDestory() { isRunning = false; for (int i = 0; i < threadNums; i++) { taskThreads[i].destroy(); } } class TaskThread extends Thread { Runnable runnable = null; @Override public void run() { //当线程池可用 无限循环 while (isRunning) { synchronized (taskqueue) { if (!taskqueue.isEmpty() && isRunning) { runnable = taskqueue.remove(0); } else { try { //等待20后释放锁锁 taskqueue.wait(20); } catch (Exception e) { e.printStackTrace(); ; } } } //记住将runnable置于同步代码块外,否则会导致一个线程占有锁时间过长 if (runnable != null) { runnable.run(); } } } } } //接下来进行测试 package com.MyThread.Mytest; public class MyThreadPoolTest { public static void main(String[] args){ MyIThreadPool myIThreadPool = MyIThreadPoolImp.getMyIThreadPool(7); for(int i =0 ;i<50;i++){ myIThreadPool.addTask(new MyTask()); } myIThreadPool.execute(); myIThreadPool.destory(); } static class MyTask implements Runnable{ @Override public void run() { System.out.println(Thread.currentThread().getName()+"处理了"); } } }
可以发现我们用7个线程就完成了我们50个任务;当然这只是简单的线程池实现 没有涉及到复杂的变化,要想更深入的立即还得去看JDK源码