• Java中级学习6多线程之线程池


    为什么使用多线程?

    每一个线程的启动和结束都是比较消耗时间和占用资源的。 

    如果在系统中用到了很多的线程,大量的启动和结束动作会导致系统的性能变卡,响应变慢。 

    为了解决这个问题,引入线程池这种设计思想。 

    步骤一:线程池设计思路

    1. 准备一个任务容器
    2. 一次性启动10个 消费者线程
    3. 刚开始任务容器是空的,所以线程都wait在上面。
    4. 直到一个外部线程往这个任务容器中扔了一个“任务”,就会有一个消费者线程被唤醒notify
    5. 这个消费者线程取出“任务”,并且执行这个任务,执行完毕后,继续等待下一次任务的到来。
    6. 如果短时间内,有较多的任务加入,那么就会有多个线程被唤醒,去执行这些任务。

    在整个过程中,都不需要创建新的线程,而是循环使用这些已经存在的线程
     编写线程池代码:
    package 回忆模式.多线程.线程池.自定义线程池;
    
    import java.util.LinkedList;
    
    /**
     * @author Dawn
     * @date 2019年6月4日21:59:00
     * @version 1.0
     * 自定义线程池
     */
    public class ThreadPool {
    	//线程池大小
    	int threadPoolSize;
    	
    	//线程容器
    	LinkedList<Runnable> tasks=new LinkedList<Runnable>();
    	
    	//试图消费者任务
    	public ThreadPool() {
    		threadPoolSize=10;
    		// 启动10个任务消费者线程
    		synchronized (tasks) {
    			for(int i=0; i<threadPoolSize; i++) {
    				new TaskConsumeThread("任务消费者线程 " + i).start();
    			}
    		}
    		
    	}
    	
    	public void add(Runnable r) {
    		synchronized (tasks) {
    			tasks.add(r);
    			// 唤醒等待的任务消费者线程
    			tasks.notifyAll();
    		}
    		
    	}
    	
    	public class TaskConsumeThread extends Thread{
    		
    		public TaskConsumeThread(String name) {
    			super(name);
    		}
    		
    		Runnable task;
    		
    		public void run() {
    			System.out.println("启动: " + this.getName());
    			while(true) {
    				synchronized (tasks) {
    					while(tasks.isEmpty()) {
    						try {
    							tasks.wait();
    						} catch (InterruptedException e) {
    							// TODO Auto-generated catch block
    							e.printStackTrace();
    						}
    					}
    					
    					task=tasks.removeLast();
    					 // 允许添加任务的线程可以继续添加任务
    					tasks.notifyAll();
    				}
    				System.out.println(this.getName() + " 获取到任务,并执行");
    				task.run();
    			}
    		}
    	}
    	
    }
    

      

    编写测试类:

    package 回忆模式.多线程.线程池.自定义线程池;
    
    /**
     * @author Dawn
     * @date 2019年6月4日22:08:44
     * @version 1.0
     * 测试自定义线程
     */
    public class TestThread {
           
        public static void main(String[] args) {
            ThreadPool pool = new ThreadPool();
      
            try {//有足够时间启动这个线程池
    			Thread.sleep(1000);
    		} catch (InterruptedException e1) {
    			// TODO Auto-generated catch block
    			e1.printStackTrace();
    		}   
            
            int sleep=1000;
            while(true){
                pool.add(new Runnable(){
                    @Override
                    public void run() {
                        System.out.println("执行任务");
                        try {
                            Thread.sleep(1000);
                        } catch (InterruptedException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        }
                    }
                });
                try {
                	//每个任务执行的时间都是1秒,刚开始是间隔1秒钟向线程池中添加任务,
                	//然后间隔时间越来越短,执行任务的线程还没有来得及结束,新的任务又来了。
                    Thread.sleep(sleep);
                    sleep = sleep>100?sleep-100:sleep;
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                  
            }
      
        }
               
    }
    

      

    运行结果:

    这里我画了一个线程池的流程图,方便理解:

  • 相关阅读:
    arcgis要素折点转点
    arcgis问题数据判断
    arcgis根据位置信息查找一个点周围的线(根据交点,查找)
    GIS算法-最短路径-连通性-网络分析-路径规划
    Arcgis直连SQLServer数据库,通过REST修改数据ArcMap中更新数据库数据不更新,数据不统一
    None和NULL
    ArcPy属性查询
    WGS84转gcj02
    ArcGIS Server跨域
    MySQL中数据类型宽度有什么用, INT(11)有什么意义?
  • 原文地址:https://www.cnblogs.com/hidamowang/p/10976698.html
Copyright © 2020-2023  润新知