多线程(1)----线程池

版权声明:未经同意,严禁转载 https://blog.csdn.net/pengchengliu/article/details/83141061

一、线程池的概念                                                                                                                              点击此处返回总目录

二、使用线程池的第一种方式:使用Runnable接口的方式

三、使用线程池的第二种方式:使用Callable接口的方式

四、练习

一、线程池的概念

线程池就是一个容器,可以容纳多个线程。

创建和销毁线程要消耗系统资源。所以可以搞一个线程池,里面存进去线程,当运行任务的时候让线程运行,运行完了之后不能死,再放回到线程池中。

以前实现线程池都是程序员自己开发的,大致思路如下:

创建一个 ArrayList<Thread>

然后add很多个new Thread()

当使用的时候:Thread t = array.remove()取出一个线程来,然后执行任务

用完之后,ayyay.add(t),再把这个线程加回去。

从JDK5以后,内置了线程池技术,就可以直接使用了。

二、使用线程池的第一种方式:使用Runnable接口的方式

与两个类有关系,一个是工厂类,一个是线程池类。线程池容器是由线程池工厂创建的。

1. Executors类        //创建线程池的工厂类。在java.util.concurrent包下面。这个类下面的方法全是静态的。

   

    常用方法:

    static ExecutorService newFixedThreadPool(int n)         //创建一个可重用固定线程数的线程池。返回的是ExecutorService接口的实现                                                                                             类的对象,即线程池对象。

2. ExecutorService接口          //这是一个接口,这个接口的实现类就是线程池类。

    常用方法:

    Future submit(Runnable r)            //参数是一个Runnable接口的对象。 返回的是Future接口的实现类。

线程池使用步骤:

1. 使用工厂类创建线程池对象,并指定线程的个数。返回ExecutorService接口的实现类对象(线程池对象)。

2. 线程池对象调用submit(Runnable r)方法,提交线程执行任务。

  

例:

//SubThread.java

package cn.itcast.demo05;

public class SubThread implements Runnable{
    public void run(){
        for(int i = 0;i<10;i++){
            System.out.println(Thread.currentThread().getName()+"..."+i);
        }
    }
}

//SubThread1.java

package cn.itcast.demo05;

public class SubThread1 implements Runnable {
    public void run(){
        for(int i = 10; i<20; i++){
            System.out.println(Thread.currentThread().getName()+"..."+i);
        }
    }
}

//Test.java

package cn.itcast.demo05;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Test {
    public static void main(String[] args) {
        ExecutorService es = Executors.newFixedThreadPool(3);        //工厂类创建线程池es
        SubThread task = new SubThread();
        SubThread1 task1 = new SubThread1();
        
        es.submit(task);
        es.submit(task);
        es.submit(task1);
    }
}

运行结果:

pool-1-thread-2...0
pool-1-thread-3...10
pool-1-thread-1...0
pool-1-thread-3...11
pool-1-thread-3...12
pool-1-thread-3...13
pool-1-thread-2...1
pool-1-thread-3...14
pool-1-thread-1...1
pool-1-thread-3...15
.......

三、使用线程池的第二种方式:使用Callable接口的方式

实现Runnable接口的方式看着挺好用,但是有两个问题:

一是,重写的是public void run()方法,没有返回值。二是run()方法没有抛出异常,所以接口的实现类也不能抛出异常。

Runnable接口已经定义好了,不能随便改。所以java又提供了另一个接口Callable。

Callable接口中有方法call(),等同于run(),但是有返回值,而且可以抛出异常。

V call() throws Exception            

使用Callable接口的方式与Runnable接口的方式差不多。

例:

//SubThread.java

package cn.itcast.demo06;

import java.util.concurrent.Callable;

public class SubThread implements Callable<String> {
    public String call(){
        return "aaa";
    }
}

//Test.java

package cn.itcast.demo06;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

public class Test {
    public static void main(String[] args) throws InterruptedException, ExecutionException {
        ExecutorService es = Executors.newFixedThreadPool(2);
        Callable<String> c = new SubThread();
        Future<String> f = es.submit(c);                                //submit的返回值是一个Future接口的实现类
        String s = f.get();                                                       //通过调用get()方法获得返回值
        System.out.println(s);
    }
}

四、练习

使用线程池技术,有两个线程,一个线程计算1加到100的和,另一个线程计算1加到200的和。

分析:

1. 既然要返回结果,肯定不能使用Runnable的方式来做,要使用Callable的方式来做。

2. 一个任务是计算1到100的和,另一个任务是计算1到200的和,不能写两个子线程,而是应当把100和200作为参数传进去。call()方法不能接受参数,如果写了参数会报错。那怎么办呢?一个巧妙的方法就是,通过构造方法传进去。在实现类中定义一个变量,然后参数通过构造方法传进去。

//SubThread.java

package cn.itcast.demo07;

import java.util.concurrent.Callable;

public class SubThread implements Callable<Integer>{
    public int a ;
    public SubThread(int a){
        this.a = a;
    }
    
    public Integer call(){
        int sum = 0 ;
        for(int i = 1;i <=a;i++){
            sum +=i;
        }
        return sum;
    }
}

//Test.java

package cn.itcast.demo07;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

public class Test {
    public static void main(String[] args) throws Exception {
        ExecutorService es = Executors.newFixedThreadPool(2);
        Future<Integer> f = es.submit(new SubThread(100));
        Future<Integer> f1 = es.submit(new SubThread(200));
        
        System.out.println(f.get());
        System.out.println(f1.get());
        
    }
}

猜你喜欢

转载自blog.csdn.net/pengchengliu/article/details/83141061