1.线程的创建方式---继承Thread类、实现Runnable接口、实现Callable接口
2.线程池的创建方式
//固定大小的线程池 static ExecutorService es1 = Executors.newFixedThreadPool(2); //当提交任务速度高于线程池中任务处理速度时,缓存线程池会不断的创建线程 static ExecutorService es2 = Executors.newCachedThreadPool(); //需要保证顺序执行各个任务的场景 static ExecutorService es3 = Executors.newSingleThreadExecutor();
3.线程启动方式
Thread的start()
通过java.util.concurrent.ExecutorService接口对象来执行任务,方式--execute、submit。差异如下
/**
* execute方法与submit方法的差别
* 1)接受的参数不一样
* 2)submit有返回值,而execute没有
* 3)submit方便Exception处理
*/
//es.execute(new Task2()); List<Future> futures = new ArrayList<>(); for(int i=0;i<5;i++){ // 使用ExecutorService的submit方法,执行Callable类型的任务 Future future=es.submit(new Task1(i)); //将任务执行结果存储到futures中 futures.add(future); } // 遍历任务的结果 try { for (Future future : futures) { if (future.get() != null) { System.out.println("单个线程是否已经处理完毕:" + future.get()); } } } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); }finally { //关闭线程池,一定要调用这个方法,不然executorService.isTerminated()永远不为true es.shutdown(); }
public class Task1 implements Callable<Object> { private int i; public Task1(int i) { this.i = i; } @Override public Object call() throws Exception { // 这里是业务逻辑处理 System.out.println("子线任务"+i+"开始执行"); // 为了能看出效果 ,让当前线程阻塞5秒 try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } // 处理完业务逻辑, return true; } }
public class Task2 extends Thread{ public void run() { // 这里是业务逻辑处理 System.out.println("子线任务开始执行"); // 为了能看出效果 ,让当前线程阻塞5秒 try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } } }