1.线程池的概念
规定一个容器来存储线程,当有任务需要是,从中取走一个线程,用完之后归还。
2.使用线程池方式--Runnable接口
先学习两个类。
ExecutorService:线程池类。
Executors:线程池创建工厂类。
1.先创建一个类,实现Runnable接口,重写run()方法
1 public class MyRunnable implements Runnable { 2 @Override 3 public void run() { 4 // TODO Auto-generated method stub 5 for (int i = 1; i < 101; i++) { 6 System.out.println(Thread.currentThread().getName()+":"+i); 7 } 8 } 9 }
2.新建测试类,获取线程池对象,创建线程任务,执行任务之后销毁任务。
1 public class demo03 { 2 public static void main(String[] args) { 3 //获取线程池对象 4 ExecutorService es = Executors.newFixedThreadPool(2);//规定存储2个线程 5 //创建线程任务对象 6 MyRunnable mr = new MyRunnable(); 7 //线程池随机选一条空闲线程执行线程任务 8 es.submit(mr); 9 es.submit(mr); 10 es.submit(mr); 11 //销毁线程池 12 es.shutdown(); 13 } 14 }
3.执行结果
可以看到,我们规定了两条线程,但开启了三个任务,所以第三个任务就会处于等待状态,等待有线程空闲之后,它再开始。
3.使用线程池方式—Callable接口
3.1区别
我们发现,使用Runnable接口时,重写该方法并不能有返回值且不能抛出异常,那我们要有返回值或要抛出异常时,就是用到Callable接口。
3.2使用
1.创建类,实现Callable接口,实现接口时,要表明泛型,这样在点击重写方法时会直接将该泛型的返回值写出,重写的方法上也可以添加异常。
1 import java.util.concurrent.Callable; 2 3 public class MyCallable implements Callable<String> { 4 public String call() throws Exception { 5 return "abc"; 6 } 7 }
2.创建测试类,获取线程池对象,创建线程任务对象,用Future接受执行对象的返回值。
1 public class demo04 { 2 public static void main(String[] args) throws InterruptedException, ExecutionException { 3 //获取线程池对象 4 ExecutorService es = Executors.newFixedThreadPool(2); 5 //创建线程任务对象 6 MyCallable mc = new MyCallable(); 7 Future<String> f = es.submit(mc); 8 //获取返回值 9 String mes = f.get(); 10 System.out.println(mes); 11 es.shutdown(); 12 } 13 }
3.执行结果
4.线程池练习:分别用两条线程计算1-100的和,1-200的和
1.首先,要先创建一个类继承Callable,泛型的话,因为是两束相加的结果,所以是Integer类型的
因为重写的方法并不能使用传参数的方法来获取数,所以使用另外一种,成员变量和构造方法的办法来获取数值。
1 public class MySum implements Callable<Integer> { 2 private int n; 3 public MySum(){} 4 public MySum(int n){ 5 this.n = n; 6 } 7 public Integer call() throws Exception { 8 int sum = 0; 9 for (int i = 1; i <= n; i++) { 10 sum+=i; 11 } 12 return sum; 13 } 14 }
2.创建测试类,按照顺序操作
1 public class demo05 { 2 //分别用两条线程计算1-100的和,1-200的和 3 public static void main(String[] args) throws InterruptedException, ExecutionException { 4 //获取线程池对象 5 ExecutorService es = Executors.newFixedThreadPool(2); 6 //创建线程任务对象 7 MySum my1 = new MySum(100); 8 MySum my2 = new MySum(200); 9 //提交线程任务 10 Future<Integer> f1 = es.submit(my1); 11 Future<Integer> f2 = es.submit(my2); 12 //获取返回值 13 System.out.println(f1.get()); 14 System.out.println(f2.get()); 15 //销毁线程池 16 es.shutdown(); 17 } 18 }