Java并发包——使用新的方式创建线程

摘要:本文主要学习了如何使用Java并发包中的类创建线程。

部分内容来自以下博客:

https://www.cnblogs.com/dolphin0520/p/3949310.html

使用Callable接口创建线程

Callable与Runnable

之前学习多线程的时候,使用java.lang包下的Runnable接口可以创建线程。

1 @FunctionalInterface
2 public interface Runnable {
3     public abstract void run();
4 }

发现由于run()方法返回值为void类型,所以在执行完任务之后无法返回任何结果。

Callable位于java.util.concurrent包下,它是一个函数式接口,在它里面声明了一个方法,只不过这个方法叫做call()。

1 @FunctionalInterface
2 public interface Callable<V> {
3     V call() throws Exception;
4 }

通过源码可以看到call()方法是一个泛型接口,可以返回V类型的数据,并且支持抛出异常。

Future

Future就是对于具体的Runnable或者Callable任务的执行结果进行取消、查询是否完成、获取结果。必要时可以通过get方法获取执行结果,该方法会阻塞直到任务返回结果。

Future类位于java.util.concurrent包下,它是一个接口:

 1 public interface Future<V> {
 2     // 用来取消任务,如果取消任务成功则返回true,如果取消任务失败则返回false。
 3     // 参数mayInterruptIfRunning表示是否允许取消正在执行的任务,如果设置true,则表示可以取消正在执行过程中的任务。
 4     // 如果任务已经完成,返回false。
 5     // 如果任务正在执行,若mayInterruptIfRunning设置为true,则返回true,若mayInterruptIfRunning设置为false,则返回false。
 6     // 如果任务还没有执行,返回true。
 7     boolean cancel(boolean mayInterruptIfRunning);
 8
 9     // 表示正在执行的任务是否被取消成功,如果在完成前被取消成功,返回true。
10     boolean isCancelled();
11
12     // 表示任务是否已经完成,若任务完成,则返回true。
13     boolean isDone();
14
15     // 用来获取执行结果,这个方法会产生阻塞,会一直等到任务执行完毕才返回。
16     V get() throws InterruptedException, ExecutionException;
17
18     // 用来获取执行结果,如果在指定时间内,还没获取到结果,就抛出TimeoutException异常。
19     V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException;
20 }

因为Future只是一个接口,所以是无法直接用来创建对象使用的,因此就有了下面的FutureTask。

FutureTask

我们先来看一下FutureTask的实现:

1 public class FutureTask<V> implements RunnableFuture<V>

FutureTask类实现了RunnableFuture接口,我们看一下RunnableFuture接口的实现:

1 public interface RunnableFuture<V> extends Runnable, Future<V>

可以看出RunnableFuture继承了Runnable接口和Future接口,而FutureTask实现了RunnableFuture接口。所以它既可以作为Runnable被线程执行,又可以作为Future得到Callable的返回值。

FutureTask提供了2个构造器:

public FutureTask(Callable<V> callable);

public FutureTask(Runnable runnable, V result);

创建线程并使用

代码如下:

 1 public class Demo {
 2     public static void main(String[] args) {
 3         FutureTask<Integer> futureTask = new FutureTask<Integer>(new NewFutureTask());
 4         new Thread(futureTask).start();
 5         try {
 6             Integer i = futureTask.get();
 7             System.out.println(i);
 8         } catch (InterruptedException e) {
 9             e.printStackTrace();
10         } catch (ExecutionException e) {
11             e.printStackTrace();
12         }
13     }
14 }
15
16 class NewFutureTask implements Callable<Integer> {
17     @Override
18     public Integer call() throws Exception {
19         System.out.println("call() ...");
20         return 100;
21     }
22 }

运行结果如下:

1 call() ...
2 100

因为FutureTask实现了RunnableFuture接口,而RunnableFuture又继承了Runnable和Future接口,所以FutureTask可以看作是Runnable的一个实现类。

所以在创建线程的时候,代码 new Thread(futureTask).start(); 实际上是通过 public Thread(Runnable target) 方法创建的线程。

使用线程池创建线程

Executor

Executor接口是线程池的顶层接口,ExecutorService接口是Executor的子接口,而ThreadPoolExecutor类实现了ExecutorService接口,是线程池的核心类。

Executors类时线程池的一个工具类,里面提供了创建线程池的几个静态方法。

下面的代码展示了使用Executors类的newFixedThreadPool()方法创建一个固定长度的线程池,并向线程池中插入任务的操作:

 1 public class Demo {
 2     public static void main(String[] args) {
 3         ExecutorService threadPool = Executors.newFixedThreadPool(3);
 4
 5         for (int i = 1; i <= 11; i++) {
 6             DemoThread dt = new DemoThread(i);
 7             threadPool.submit(dt);
 8         }
 9         threadPool.shutdown();
10     }
11 }
12
13 class DemoThread implements Runnable {
14     int taskNo = 0;
15
16     public DemoThread(int taskNo) {
17         this.taskNo = taskNo;
18     }
19
20     @SuppressWarnings("static-access")
21     public void run() {
22         try {
23             System.out.println("task " + taskNo);
24             Thread.currentThread().sleep(4000);
25         } catch (InterruptedException e) {
26             e.printStackTrace();
27         }
28     }
29 }

结果如下:

 1 task 1
 2 task 3
 3 task 2// 此处有等待。
 4 task 4
 5 task 5
 6 task 6// 此处有等待。
 7 task 7
 8 task 9
 9 task 8// 此处有等待。
10 task 10
11 task 11

结果说明:

可以看到因为设置的线程数为3,所以在创建了3个线程之后,将剩下的任务放在了任务队列里,当有任务执行完成之后再将其取出执行。

转载于:https://www.cnblogs.com/shamao/p/11015558.html

Java并发包——使用新的方式创建线程相关推荐

  1. python线程创建对象_Python使用面向对象方式创建线程实现12306售票系统

    目前python 提供了几种多线程实现方式 thread,threading,multithreading ,其中thread模块比较底层,而threading模块是对thread做了一些包装,可以更 ...

  2. Java多线程学习总结(7)——创建线程池的正确姿势

    一. 通过Executors创建线程池的弊端 在创建线程池的时候,大部分人还是会选择使用Executors去创建. 下面是创建定长线程池(FixedThreadPool)的一个例子,严格来说,当使用如 ...

  3. Runnable方式创建线程详解

    2.4创建线程的方式二 创建线程的第二种方式.使用Runnable接口. 该类中的代码就是对线程要执行的任务的定义. 1:定义了实现Runnable接口 2:重写Runnable接口中的run方法,就 ...

  4. java runnable接口 sleep_java Runnable接口如何创建线程

    java Runnable接口如何创建线程 导语:编写多线程程序是为了实现多任务的并发执行,从而能够更好地与用户交互.下面是java Runnable接口创建线程的相关资料,欢迎阅读: java Ru ...

  5. java thread 多线程_java用Thread方式创建多线程

    进程:一个正在执行的程序,每一个进程都有一个执行顺序,该 顺序是一个执行路径,或者叫一个控制单元. 线程:进程中一个独立的控制单元.线程控制着进程的执行. 一个进程中至少有一个线程. java VM中 ...

  6. Java多线程(6)--Callable接口创建线程

    与使用Runnable相比, Callable功能更强大些 ①相比run()方法,可以有返回值 ②方法可以抛出异常 ③支持泛型的返回值 ④需要借助FutureTask类,可以获取返回结果 Future ...

  7. Java 创建线程的三种方式

    一.继承Thread类创建 1.定义一个类继承Thread类,并重写Thread类的run()方法,run()方法的方法体就是线程要完成的任务,因此把run()称为线程的执行体: 2.创建该类的实例对 ...

  8. Java多线程 - Java创建线程的4种方式

    文章目录 1. Java创建线程有哪几种方式? 1.1 线程创建方法一:继承Thread类创建线程类 1.2 线程创建方法二:实现Runnable接口创建线程目标类 1.5 线程创建方法三:使用Cal ...

  9. java创建线程(Thread)的5种方式

    java创建线程(Thread)的5种方式 方式一:继承于Thread类 方式二:实现Runnable接口 方式三:实现Callable接口 方式四:使用线程池 方式五:使用匿名类 方式一:继承于Th ...

最新文章

  1. 瑞雪时晴,不亦快哉 ——图灵十一月月刊
  2. 关于ANSI和UTF-8,windows和unix的行结束符
  3. petalinux zynq spi_ZYNQ 系列 01 | PL 实现按键控制 LED(1)
  4. SAP本地化-银企直连
  5. 为什么 MySQL 回滚事务也会导致 ibd 文件增大?
  6. 1.3编程基础之算术表达式与顺序执行 01 A+B问题
  7. pyqt5实时动态曲线
  8. 小米POCO X3今日亮相:首发骁龙732G后置6400万四摄
  9. 兰亭集势笔试题:用最优方法从LinkedList列表中删除重复元素
  10. 让网页附件为Word或Excel的文件,下载时直接弹出下载对话框,而不打开它
  11. 象棋名手手机版2019最新版_象棋名手64核比赛冠军版2019
  12. Linux使用Wget实现整站下载
  13. 通过调用百度生成短连接API接口,将长链接转换成短链接,并且生成短网址并返回,用户可以通过短连接访问,然后浏览器会解析跳转至长链接地址,有效的解决用户修改url后面的参数
  14. thinkpadt410接口介绍_【ThinkPadT410s(2912BR7)评测】丰富接口满足日常所需-中关村在线...
  15. linux系统连接校园无线网卡,Linux连接校园网
  16. 将用户需求转成产品需求
  17. Python数据可视化之南丁格尔玫瑰图
  18. TCP/UDP 区别
  19. 第2章 C语言的数值数据与非数值数据 (二)
  20. 广东省谷歌地球高程DEM等高线下载

热门文章

  1. 从小白到大数据技术专家的学习历程,你准备好了吗
  2. docker学习总结二
  3. 搭建svn,创建svn项目
  4. Android ListView中 每一项都有不同的布局
  5. 误区30日谈21-24
  6. .net MVC在服务端代码输出html字符串
  7. 多个DataTable的合并成一个新表
  8. ******:突破空格的限制
  9. android 点动态显示图片,Android用RecyclerView实现动态添加本地图片
  10. messagebox 全部使用_商业篇 | 使用python开发性格分析工具卖钱