zoukankan      html  css  js  c++  java
  • Java并发编程核心方法与框架-Executors的使用

    合理利用线程池能够带来三个好处
    1. 降低资源消耗。通过重复利用已创建的线程降低线程创建和销毁造成的消耗。
    2. 提高响应速度。当任务到达时,任务可以不需要等到线程创建就能立即执行。
    3. 提高线程的可管理性。线程是稀缺资源,如果无限制的创建,不仅会消耗系统资源,还会降低系统的稳定性,使用线程池可以进行统一的分配,调优和监控。

    官方建议使用Executors工厂类来创建线程池对象

    使用newCachedThreadPool()方法创建无界线程池

    使用Executors类的newCachedThreadPool()方法创建的是无界线程池,可以进行线程自动回收。所谓的“无界线程池”就是池中存放线程个数理论上是Integer.MAX_VALUE。

    public class Run1 {
    	public static void main(String[] args) {
    		ExecutorService executorService = Executors.newCachedThreadPool();
    		executorService.execute(new Runnable() {
    			
    			@Override
    			public void run() {
    				try {
    					System.out.println("Runnable1 begin:" + System.currentTimeMillis());
    					Thread.sleep(1000);
    					System.out.println("A");
    					System.out.println("Runnable1 end:" + System.currentTimeMillis());
    				} catch (InterruptedException e) {
    					e.printStackTrace();
    				}
    			}
    		});
    		executorService.execute(new Runnable() {
    			
    			@Override
    			public void run() {
    				try {
    					System.out.println("Runnable2 begin:" + System.currentTimeMillis());
    					Thread.sleep(1000);
    					System.out.println("A");
    					System.out.println("Runnable2 end:" + System.currentTimeMillis());
    				} catch (InterruptedException e) {
    					e.printStackTrace();
    				}				
    			}
    		});
    	}
    }
    

    程序运行结果如下:

    Runnable1 begin:1470228063076
    Runnable2 begin:1470228063076
    A
    A
    Runnable2 end:1470228064081
    Runnable1 end:1470228064081
    

    线程池的线程复用效果
    public class MyRunnable implements Runnable {
    	private String username;
    	public MyRunnable(String username) {
    		super();
    		this.username = username;
    	}
    	@Override
    	public void run() {
    		System.out.println(Thread.currentThread().getName() + " username=" + username + " begin:" + System.currentTimeMillis());
    		System.out.println(Thread.currentThread().getName() + " username=" + username + " end:" + System.currentTimeMillis());
    	}
    }
    
    public class Main {
    	public static void main(String[] args) throws InterruptedException {
    		ExecutorService executorService = Executors.newCachedThreadPool();
    		for (int i = 0; i < 5; i++) {
    			executorService.execute(new MyRunnable("" + i));
    		}
    		Thread.sleep(2000);
    		System.out.println();
    		for (int i = 0; i < 5; i++) {
    			executorService.execute(new MyRunnable("" + i));
    		}
    	}
    }
    

    程序运行结果如下:

    pool-1-thread-1 username=0 begin:1470229448635
    pool-1-thread-4 username=3 begin:1470229448635
    pool-1-thread-3 username=2 begin:1470229448635
    pool-1-thread-2 username=1 begin:1470229448635
    pool-1-thread-3 username=2 end:1470229448635
    pool-1-thread-4 username=3 end:1470229448635
    pool-1-thread-5 username=4 begin:1470229448635
    pool-1-thread-1 username=0 end:1470229448635
    pool-1-thread-5 username=4 end:1470229448636
    pool-1-thread-2 username=1 end:1470229448635
    
    pool-1-thread-1 username=2 begin:1470229450637
    pool-1-thread-3 username=4 begin:1470229450637
    pool-1-thread-3 username=4 end:1470229450637
    pool-1-thread-2 username=0 begin:1470229450637
    pool-1-thread-2 username=0 end:1470229450638
    pool-1-thread-5 username=1 begin:1470229450637
    pool-1-thread-4 username=3 begin:1470229450637
    pool-1-thread-4 username=3 end:1470229450638
    pool-1-thread-5 username=1 end:1470229450638
    pool-1-thread-1 username=2 end:1470229450637
    

    由打印结果可见,第一次for循环中创建了5个线程对象分别是pool-1-thread-1到pool-1-thread-5,第二次for循环中没有创建新的线程对象,复用了第一次for循环中创建的线程对象。


    使用newCachedThreadPool(ThreadFactory)定制线程工厂
    public class MyThreadFactory implements ThreadFactory {
    	@Override
    	public Thread newThread(Runnable r) {
    		Thread thread = new Thread(r);
    		thread.setName("定制池中线程对象的名称" + Math.random());
    		return thread;
    	}
    }
    
    public class Run {
    	public static void main(String[] args) {
    		MyThreadFactory myThreadFactory = new MyThreadFactory();
    		ExecutorService executorService = Executors.newCachedThreadPool(myThreadFactory);
    		executorService.execute(new Runnable() {
    			
    			@Override
    			public void run() {
    				System.out.println(Thread.currentThread().getName() + "运行:" + System.currentTimeMillis());
    			}
    		});
    	}
    }
    

    程序运行结果如下:

    定制池中线程对象的名称0.2671917944865071运行:1470230269473
    

    使用newFixedThreadPool(int)方法创建有界线程池
    public class MyRunnable implements Runnable {
    	String username;
    	public MyRunnable(String username) {
    		super();
    		this.username = username;
    	}
    	@Override
    	public void run() {
    		try {
    			System.out.println(Thread.currentThread().getName() + " username=" + username + " begin:" + System.currentTimeMillis());
    			Thread.sleep(2000);
    			System.out.println(Thread.currentThread().getName() + " username=" + username + " end:" + System.currentTimeMillis());
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
    	}
    }
    
    public class Run {
    	public static void main(String[] args) {
    		ExecutorService executorService = Executors.newFixedThreadPool(3);
    		for (int i = 0; i < 3; i++) {
    			executorService.execute(new MyRunnable("" + i));
    		}
    		for (int i = 0; i < 3; i++) {
    			executorService.execute(new MyRunnable("" + i));
    		}
    	}
    }
    

    程序运行结果如下:

    pool-1-thread-1 username=0 begin:1470230865037
    pool-1-thread-3 username=2 begin:1470230865037
    pool-1-thread-2 username=1 begin:1470230865037
    pool-1-thread-3 username=2 end:1470230867043
    pool-1-thread-1 username=0 end:1470230867042
    pool-1-thread-3 username=0 begin:1470230867043
    pool-1-thread-1 username=1 begin:1470230867043
    pool-1-thread-2 username=1 end:1470230867043
    pool-1-thread-2 username=2 begin:1470230867043
    pool-1-thread-3 username=0 end:1470230869047
    pool-1-thread-1 username=1 end:1470230869047
    pool-1-thread-2 username=2 end:1470230869047
    

    此时线程池中最多有三个线程。


    使用newFixedThreadPool(int, ThreadFactory)定制线程工厂
    public class MyThreadFactory implements ThreadFactory {
    	@Override
    	public Thread newThread(Runnable r) {
    		Thread thread = new Thread(r);
    		thread.setName("定制池中线程对象的名称" + Math.random());
    		return thread;
    	}
    }
    
    public class Run {
    	public static void main(String[] args) {
    		MyThreadFactory threadFactory = new MyThreadFactory();
    		ExecutorService executorService = Executors.newFixedThreadPool(2, threadFactory);
    		Runnable runnable = new Runnable() {
    			
    			@Override
    			public void run() {
    				try {
    					System.out.println("begin 我在运行" + System.currentTimeMillis() + " " + Thread.currentThread().getName());
    					Thread.sleep(2000);
    					System.out.println("end 我在运行" + System.currentTimeMillis() + " " + Thread.currentThread().getName());
    				} catch (InterruptedException e) {
    					e.printStackTrace();
    				}
    				
    			}
    		};
    		executorService.execute(runnable);
    		executorService.execute(runnable);
    		executorService.execute(runnable);
    	}
    }
    

    程序运行结果如下:

    begin 我在运行1470231214770 定制池中线程对象的名称0.07643716796315236
    begin 我在运行1470231214770 定制池中线程对象的名称0.5060032203497645
    end 我在运行1470231216773 定制池中线程对象的名称0.5060032203497645
    end 我在运行1470231216773 定制池中线程对象的名称0.07643716796315236
    begin 我在运行1470231216773 定制池中线程对象的名称0.5060032203497645
    end 我在运行1470231218774 定制池中线程对象的名称0.5060032203497645
    

    使用newSingleThreadExecutor()方法创建单一线程池
    public class MyRunnable implements Runnable {
    	String username;
    	public MyRunnable(String username) {
    		super();
    		this.username = username;
    	}
    	@Override
    	public void run() {
    		try {
    			System.out.println(Thread.currentThread().getName() + " username=" + username + " begin:" + System.currentTimeMillis());
    			Thread.sleep(2000);
    			System.out.println(Thread.currentThread().getName() + " username=" + username + " end:" + System.currentTimeMillis());
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
    	}
    }
    
    public class Run {
    	public static void main(String[] args) {
    		ExecutorService executorService = Executors.newSingleThreadExecutor();
    		for (int i = 0; i < 3; i++) {
    			executorService.execute(new MyRunnable("" + i));
    		}
    	}
    }
    

    程序运行结果如下:

    pool-1-thread-1 username=0 begin:1470231470978
    pool-1-thread-1 username=0 end:1470231472978
    pool-1-thread-1 username=1 begin:1470231472978
    pool-1-thread-1 username=1 end:1470231474982
    pool-1-thread-1 username=2 begin:1470231474982
    pool-1-thread-1 username=2 end:1470231476984
    

    此时线程池中只有一个线程。

    newSingleThreadExecutor(ThreadFactory) 使用方法与前面的大体一致。

  • 相关阅读:
    Hash索引与B-Tree索引
    Android -- taskAffinity
    Android -- getSystemService
    Android面试,与Service交互方式
    Quartz.NET开源作业调度框架系列(四):Plugin Job-转
    Quartz.NET开源作业调度框架系列(三):IJobExecutionContext 参数传递-转
    Quartz.NET开源作业调度框架系列(一):快速入门step by step-转
    Quartz.NET开源作业调度框架系列(二):CronTrigger-转
    quartz.net 的配置文件资料
    基于.net 的加载自定义配置-误操作
  • 原文地址:https://www.cnblogs.com/umgsai/p/5671645.html
Copyright © 2011-2022 走看看