• 线程池的单例构造与使用


    1.做一个线程池的工具类(最简单的)

    package cn.xdf.wlyy.thread;
    
    import java.util.concurrent.ArrayBlockingQueue;
    import java.util.concurrent.ThreadPoolExecutor;
    import java.util.concurrent.TimeUnit;
    
    
    public class ThreadPool {
        // 单例,让池子只有一个  
        private ThreadPool() {  
        };  
      
        private static ThreadPool tp;  
      
        public static ThreadPool getInstance() {  
            if (tp == null) {  
                tp = new ThreadPool();  
            }  
            return tp;  
        }  
      
        // 构造一个任务池  
        // 参数说明:  
        // corePoolSize - 池中所保存的线程数,包括空闲线程。  
        // maximumPoolSize - 池中允许的最大线程数。  
        // keepAliveTime - 当线程数大于核心时,此为终止前多余的空闲线程等待新任务的最长时间。  
        // unit - keepAliveTime 参数的时间单位。  
        // workQueue - 执行前用于保持任务的队列。此队列仅保持由 execute 方法提交的 Runnable 任务。  
        // threadFactory - 执行程序创建新线程时使用的工厂。  
        // handler - 由于超出线程范围和队列容量而使执行被阻塞时所使用的处理程序。  
        ThreadPoolExecutor executor = new ThreadPoolExecutor(5, 10, 200, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(5));
      
        // 在池子里取一个线程执行任务  
        public void execute(Runnable task) {  
        	executor.execute(task);  
        } 
        
        public void shutdown() {
        	executor.shutdown();
        }
    }
    

    2.看是否需要返回值,不需要的话就实现Runnable接口,重写run方法;需要的话就要实现Callable接口,重写call方法。而run与call方法中是我们要多线程的业务代码


    2.1不需要返回用这个类

    package cn.xdf.wlyy.thread;
    
    import cn.xdf.wlyy.util.DateUtil;
    
    
    public class TestTask implements Runnable {  
        
        //如果我们的任务需要一些数据,可以通过构造方法传进来  
        String param;  
        public TestTask(String param){  
            this.param = param;  
        }  
          
        public void run() {
            System.out.println("正在执行task "+param + "," + DateUtil.getDateTime());
            try {
                Thread.currentThread().sleep(4000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("task "+param+"执行完毕," + DateUtil.getDateTime());
        }  
        
        public static void main(String args[]){
            for(int i=0;i<15;i++){
            	//得到我们的池子  
            	ThreadPool tp = ThreadPool.getInstance();  
                //将我们的任务new出来  
                TestTask tt = new TestTask(i + "");  
                //用池子执行任务  
                tp.execute(tt); 
            }
            
        }  
      
    } 

    2.2需要返回的话用这个类

    package cn.xdf.wlyy.thread;
    
    import java.util.concurrent.Callable;
    import java.util.concurrent.FutureTask;
    import java.util.concurrent.TimeUnit;
    
    import cn.xdf.wlyy.util.DateUtil;
    
    public class TestCallble implements Callable<String> {
    
    	// 如果我们的任务需要一些数据,可以通过构造方法传进来
    	String param;
    
    	public TestCallble(String param) {
    		this.param = param;
    	}
    
    	@Override
    	public String call() throws Exception {
    		System.out.println("正在执行task " + param + "," + DateUtil.getDateTime());
    		try {
    			System.out.println(Thread.currentThread().getName());
    			Thread.currentThread().sleep(4000);
    		}
    		catch (InterruptedException e) {
    			e.printStackTrace();
    		}
    		System.out.println("task " + param + "执行完毕," + DateUtil.getDateTime());
    		return param;
    	}
    
    	public static void main(String args[]) {
    		for (int i = 0; i < 15; i++) {
    			// 得到我们的池子
    			ThreadPool tp = ThreadPool.getInstance();
    			// 将我们的任务new出来
    			TestCallble tt = new TestCallble(i + "");
    
    			FutureTask<String> dbtask = new FutureTask<String>(tt);
    			// 用池子执行任务
    			tp.execute(dbtask);
    
    			// 在这里可以做别的任何事情
    			String result = null;
    			try {
    				// 取得结果,同时设置超时执行时间为1秒。同样可以用future.get(),不设置执行超时时间取得结果
    				result = dbtask.get(3000, TimeUnit.MILLISECONDS);
    				// result = dbtask.get();
    			}
    			catch (Exception e) {
    				dbtask.cancel(true);
    				// 超时后,进行相应处理
    			}
    			finally {
    				System.out.println("task@" + i + ":result=" + result);
    			}
    		}
    
    	}
    
    }

    值得说明的事,如果要返回值的话,只需调用futureTask.get()方法(可以设置等待时间),但如果添加了这个,那么call中的sleep必然要等,形成阻塞,一条条的获取调用结果值。而如果不加的话,就跟run方法一样,例如ThreadPoolExecutor中的参数corePoolSize(核心线程数)为5,正常来说5次一起执行,但加了get方法只能一次次执行。失去了多线程的意义了。

    我也是初学,还在找解决办法...

  • 相关阅读:
    CR, LF, CR/LF区别与关系
    利用 jQuery 克隆 Object
    【2015】网易前端面经
    前端架构:Angular与requirejs集成实践
    高质量代码之HTML、CSS篇
    【转】requirejs简单入门
    2014搜狗前端面经【B事业部】
    2014小型公司前端面经
    【转】对象创建模式
    2014搜狗前端面经【A事业部】
  • 原文地址:https://www.cnblogs.com/dulinan/p/12033039.html
Copyright © 2020-2023  润新知