今天看了线程池的源码,实现了一下线程池的思想。(第一次写的时候还死锁了···)
    其实线程池最大的问题在于,如何让线程一直活着。毕竟线程执行完run方法就会变成终止态。如果不能一直活着,也就无法池化了。
    解决线程一直活着的方法就是让线程在run方法中不断访问父作用域的阻塞队列获取任务。阻塞队列中的阻塞方法帮助线程阻塞,延长它的寿命。

    1. public class MyThreadPool {
    2. class Worker implements Runnable{
    3. private Runnable task;
    4. private Thread thread;
    5. public Worker() {
    6. this.task = null;
    7. //这里一开始死锁了
    8. }
    9. @Override
    10. public void run() {
    11. work(this);
    12. }
    13. }
    14. private void work(Worker worker) {
    15. while (true) {
    16. try {
    17. if (worker.task == null) {
    18. worker.task = works.take();
    19. worker.task.run();
    20. worker.task = null;
    21. }
    22. } catch (InterruptedException e) {
    23. e.printStackTrace();
    24. }
    25. }
    26. }
    27. private final BlockingQueue<Runnable> works;
    28. private final HashSet<Worker> workers;
    29. public MyThreadPool(){
    30. works = new ArrayBlockingQueue<>(10);
    31. workers = new HashSet<>();
    32. for (int i=0; i<5; i++) {
    33. Worker worker = new Worker();
    34. Thread t = new Thread(worker);
    35. worker.thread = t;
    36. t.start();
    37. }
    38. }
    39. public void execute(Runnable runnable) {
    40. works.offer(runnable);
    41. }
    42. // public static MyThreadPool getSingleton() {
    43. // return singleton;
    44. // }
    45. // private static final MyThreadPool singleton = new MyThreadPool();
    46. public static void main(String[] args) {
    47. MyThreadPool pool = new MyThreadPool();
    48. try {
    49. while (true) {
    50. pool.execute(() -> {
    51. try {
    52. System.out.println(Thread.currentThread().getName() + "在干活,花费一秒");
    53. Thread.sleep(1000);
    54. } catch (InterruptedException e) {
    55. e.printStackTrace();
    56. }
    57. });
    58. Thread.sleep(500);
    59. }
    60. } catch (InterruptedException e) {
    61. e.printStackTrace();
    62. }
    63. }
    64. }

    最开始没处理好worker类的构造函数,在里面直接初始化thread导致了循环引用问题。
    解决方法就是在后面用set方法(这里是包作用域所以不用写setter,但是本质是setter)单独赋值,把环破开即可。