创建多线程的原始两种方式
1、继承Thread类
2、实现Runable接口
jdk5新增的两种方式
1、实现Callable接口
jdk5:新增创建线程方式:实现Callable
* 与使用Runnable相比,Callable功能更强大
* 1、相比run() 方法,可以有返回值
* 2、方法可以抛出异常
* 3、支持泛型的返回值
* 4、需要借助FutureTask类,比如获取返回结果
* Futrue接口
* 1、可以对具体Runnable、Callable任务的执行结果进行取消、查询、是否完成、获取结果等
* 2、FutureTask同时实现了Runnable、Future接口。它既可以作为Runnable被线程执行,
* 又可以作为Future得到Callable的返回值
如何理解实现Callable接口比实现Runnable接口创建多线程的功能强大
* 1、创建call方法可以有返回值
* 2、可以抛出异常,被外面操作捕获,获取异常信息
* 3、Callable支持泛型 (安全)
package callable_test; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.FutureTask; /** * 创建线程的方式三: * jdk5:新增创建线程方式:实现Callable * 与使用Runnable相比,Callable功能更强大 * 1、相比run() 方法,可以有返回值 * 2、方法可以抛出异常 * 3、支持泛型的返回值 * 4、需要借助FutureTask类,比如获取返回结果 * * Futrue接口 * 1、可以对具体Runnable、Callable任务的执行结果进行取消、查询、是否完成、获取结果等 * 2、FutureTask同时实现了Runnable、Future接口。它既可以作为Runnable被线程执行, * 又可以作为Future得到Callable的返回值 * * 如何理解实现Callable接口比实现Runnable接口创建多线程的功能强大 * 1、创建call方法可以有返回值 * 2、可以抛出异常,被外面操作捕获,获取异常信息 * 3、Callable支持泛型 (安全) * @author Gary * @time 2019年8月22日 */ //1、创建一个实现Callable接口的实现类 class NumThread2 implements Callable { int sum = 0; //2、实现call方法 类同run() public Object call() throws Exception { for(int i=0; i<100; i++) { if(i%2==0) { System.out.println(Thread.currentThread().getName()+"="+i); sum += i; } } return sum; } } public class TestCallable { public static void main(String[] args) { //3、创建Callable接口实现类的对象 NumThread2 numT2 = new NumThread2(); //4、将次Callable接口实现类的对象作为传递到FutureTask构造器中,创建FutureTask的对象 FutureTask<NumThread2> ft = new FutureTask<NumThread2>(numT2); Thread thread = new Thread(ft); thread.start(); try { //6、获取Callable中call方法的返回值 //get方法的返回值即为FutureTask构造器参数Callable实现类重写的call()的返回值 Object sum = ft.get(); System.out.println("ft.get() = "+sum ); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (ExecutionException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
2、使用线程池
* ExecutorService:真正的线程池接口。常见子类ThreadPoolExecutor
* void execute(Runnable command): 执行任务、命令,没有返回值,一般用来执行Runnable
* <T>Future<T>submit(Callable<T>task): 执行任务,有返回值,一般用来执行Callable
* void shutdown(): 关闭连接池
*
* 使用线程池创建线程
* Executors: 工具类,线程池的工厂类,用于创建并返回不同类型的线程池
* Executors.newCachedThreadPool(): 创建一个可根据需要创建新线程的线程池
* Executors.newFixedThreadPool(): 创建一个可重用固定线程数的线程池
* Executors.newSingleThreadExecutor(): 创建一个只有一个线程额线程池
* Executors.newScheduledThreadPool(n): 创建一个线程池,他可安排在给定延迟后运行命令或者定期的执行
*
* 创建多线程有4中方式:
* 1、继承Thread类
* 2、实现Runnable接口
* 3、实现Callable接口
* 4、使用多线程
package pool; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.ThreadPoolExecutor; /** * ExecutorService:真正的线程池接口。常见子类ThreadPoolExecutor * void execute(Runnable command): 执行任务、命令,没有返回值,一般用来执行Runnable * <T>Future<T>submit(Callable<T>task): 执行任务,有返回值,一般用来执行Callable * void shutdown(): 关闭连接池 * * 使用线程池创建线程 * Executors: 工具类,线程池的工厂类,用于创建并返回不同类型的线程池 * Executors.newCachedThreadPool(): 创建一个可根据需要创建新线程的线程池 * Executors.newFixedThreadPool(): 创建一个可重用固定线程数的线程池 * Executors.newSingleThreadExecutor(): 创建一个只有一个线程额线程池 * Executors.newScheduledThreadPool(n): 创建一个线程池,他可安排在给定延迟后运行命令或者定期的执行 * * 创建多线程有4中方式: * 1、继承Thread类 * 2、实现Runnable接口 * 3、实现Callable接口 * 4、使用多线程 * @author Gary * @time 2019年8月22日 */ public class Test1 { public static void main(String[] args) { //1、提供指定线程数量的线程池 ExecutorService service = Executors.newFixedThreadPool(3); ThreadPoolExecutor service1 = (ThreadPoolExecutor)service; // 设置线程池的属性 service1.setCorePoolSize(2); System.out.println(service.getClass()); //2、执行指定的线程的操作,需要提供实现的Runnable接口或Callable接口实现类对象 service.execute(new NumberThread()); //适用于Runnable service.execute(new NumberThread()); //3、关闭连接池 service.shutdown(); // service.submit(); // 适用于Callable } } class NumberThread implements Runnable { public void run() { for(int i=0; i<100; i++) { System.out.println(Thread.currentThread().getName()+"=="+i); } } }