创建线程一般有如下几个方式:

1. 通过继承Thread类来创建一个线程:

  1. /**
  2. * 步骤1:定义一个继承Thread类的子类
  3. * 步骤2:构造子类的一个对象
  4. * 步骤3:启动线程:
  5. * */
  6. public class ThreadTest{
  7. public static void main(String[] args) {
  8. //构造子类对象
  9. SubThread subThread = new SubThread();
  10. //启动线程
  11. subThread.start();
  12. }
  13. }
  14. //定义继承Thread的子类
  15. class SubThread extends Thread{
  16. public void run(){
  17. System.out.println("Thread test.......");
  18. }
  19. }

2. 通过实现Runnable接口来创建一个线程(静态代理模式)

  1. /**
  2. * 静态代理模式的步骤
  3. * 步骤一: 创建真实角色
  4. * 步骤二: 创建代理角色,持有真实角色的引用
  5. * 步骤三: 两者实现相同的接口
  6. **/
  7. public class RunnableTest {
  8. public static void main(String[] args) {
  9. //创建一个类对象
  10. Runnable subRunnable = new SubRunnable();
  11. //由Runnable创建一个Thread对象
  12. Thread subThread = new Thread(subRunnable);
  13. //启动线程
  14. subThread.start();
  15. }
  16. }
  17.  
  18. //创建实现Runnable接口的类
  19. class SubRunnable implements Runnable{
  20. @Override
  21. public void run() {
  22. System.out.println("Runnable Test......");
  23. }
  24. }

3、通过实现Callable接口来创建一个线程(可返回值,对外声明异常等)

  1. /*
  2. * 步骤一:创建Callable接口的实现类,并重写call()方法
  3. * 步骤二:借助执行调度服务ExecutorService获取Future对象
  4. * 步骤三: get()方法获取值
  5. * 步骤四: shutdownNow()方法停止服务
  6. */
  7. public class CallableTest {
  8. public static void main(String[] args) {
  9. //借助执行调度服务ExecutorService获取Future对象
  10. ExecutorService ser = Executors.newFixedThreadPool(2);
  11. Race test1 = new Race("LiLei");
  12. Race test2 = new Race("HanMeimei");
  13. Future<String> res1 = ser.submit(test1);
  14. Future<String> res2 = ser.submit(test2);
  15.  
  16. try {
  17. //get()方法获取值
  18. System.out.println(res1.get());
  19. System.out.println(res2.get());
  20. } catch (InterruptedException e) {
  21. e.printStackTrace();
  22. } catch (ExecutionException e) {
  23. e.printStackTrace();
  24. }
  25. //shutdownNow()方法停止服务
  26. ser.shutdownNow();
  27. }
  28. }
  29.  
  30. //创建Callable接口的实现类
  31. class Race implements Callable<String> {
  32. private String name;
  33.  
  34. public Race(String name) {
  35. super();
  36. this.name = name;
  37. }
  38.  
  39. public String getName() {
  40. return name;
  41. }
  42.  
  43. public void setName(String name) {
  44. this.name = name;
  45. }
  46.  
  47. @Override
  48. public String call() throws Exception {
  49. return "Hello "+ name +"......";
  50. }
  51. }

总结:

1、推荐使用接口,原因如下:

  1)避免单继承的局限性;

  2)便于共享资源

2、两种实现接口的方式(Runnable和Callable)的区别:

  1)Callable的启动方法是call(),Runnable的启动方法是run()

  2)Callable的任务执行后可返回值,而Runnable的任务无返回值

  3)Callable的call方法可以抛出异常,Runnable的run方法不可以

  4)Callable任务可以获取Future对象,这个对象提供了检查计算是否完成的方法,以等待计算的完成,并检索计算的结果。

     通过Future对象可以了解任务执行情况,可取消任务的执行,还可获取执行结果。

   

JAVA并发编程学习笔记------线程的三种创建方式的更多相关文章

  1. Java并发编程学习笔记

    Java编程思想,并发编程学习笔记. 一.基本的线程机制 1.定义任务:Runnable接口 线程可以驱动任务,因此需要一种描述任务的方式,这可以由Runnable接口来提供.要想定义任务,只需实现R ...

  2. Java并发编程学习笔记 深入理解volatile关键字的作用

    引言:以前只是看过介绍volatile的文章,对其的理解也只是停留在理论的层面上,由于最近在项目当中用到了关于并发方面的技术,所以下定决心深入研究一下java并发方面的知识.网上关于volatile的 ...

  3. Java并发编程学习:线程安全与锁优化

    本文参考<深入理解java虚拟机第二版> 一.什么是线程安全? 这里我借<Java Concurrency In Practice>里面的话:当多个线程访问一个对象,如果不考虑 ...

  4. [转]JAVA并发编程学习笔记之Unsafe类

    1.通过Unsafe类可以分配内存,可以释放内存:类中提供的3个本地方法allocateMemory.reallocateMemory.freeMemory分别用于分配内存,扩充内存和释放内存,与C语 ...

  5. JAVA并发编程学习笔记------多线程调优

    1. 多线程场景下尽量使用并发容器代替同步容器 (如ConcurrentHashMap代替同步且基于散列的Map, 遍历操作为主要操作的情况下用CopyOnWriteArrayList代替同步的Lis ...

  6. Java 并发编程学习笔记 理解CLH队列锁算法

    CLH算法实现 CLH队列中的结点QNode中含有一个locked字段,该字段若为true表示该线程需要获取锁,且不释放锁,为false表示线程释放了锁.结点之间是通过隐形的链表相连,之所以叫隐形的链 ...

  7. java多线程总结一:线程的两种创建方式及比较

    1.线程的概念:线程(thread)是指一个任务从头至尾的执行流,线程提供一个运行任务的机制,对于java而言,一个程序中可以并发的执行多个线程,这些线程可以在多处理器系统上同时运行.当程序作为一个应 ...

  8. java多线程总结一:线程的两种创建方式及优劣比较

    1.通过实现Runnable接口线程创建 (1).定义一个类实现Runnable接口,重写接口中的run()方法.在run()方法中加入具体的任务代码或处理逻辑. (2).创建Runnable接口实现 ...

  9. Java并发编程学习笔记(三)——对象的组合

    重要概念: 1.在设计线程安全类的过程中,需要包含以下三个基本要素: (1)找出构成对象状态的所有变量. (2)找出约束状态变量的不变性条件. (3)建立对象状态的并发访问管理策略. 2.

随机推荐

  1. [bzoj2594][Wc2006]水管局长数据加强版 (lct)

    论蒟蒻的自我修养T_T.. 和noi2014魔法森林基本一样...然而数据范围大得sxbk...UPD:这题如果用lct判联通的话可能会被卡到O(mlogm)..所以最好还是用并查集吧 一开始数组开太 ...

  2. codeforces 746C 模拟

    C. Tram time limit per test 1 second memory limit per test 256 megabytes input standard input output ...

  3. 【Keras】基于SegNet和U-Net的遥感图像语义分割

    上两个月参加了个比赛,做的是对遥感高清图像做语义分割,美其名曰"天空之眼".这两周数据挖掘课期末project我们组选的课题也是遥感图像的语义分割,所以刚好又把前段时间做的成果重新 ...

  4. JAVA爬虫实践(实践四:webMagic和phantomjs和淘宝爬虫)

    webMagic虽然方便,但是也有它不适用的地方,比如定向的某个单页面爬虫,或者存在大量ajax请求,页面的跳转请求全都混淆在js里. 这时可以用webMagic结合phantomjs来真实模拟页面请 ...

  5. 人生苦短,我用Python 第一篇

    一.变量名 自定义变量名只能用 数字.字母.下划线组成. 使用变量前,需对其先赋值 注意:1.变量名不能以数字开头:      2.不能是关键字:例如:'and', 'as', 'assert', ' ...

  6. SSM手把手整合教程&测试事务

    自打来了博客园就一直在看帖,学到了很多知识,打算开始记录的学习到的知识点 今天我来写个整合SpringMVC4 spring4 mybatis3&测试spring事务的教程,如果有误之处,还请 ...

  7. Centos系统下Lamp环境的快速搭建(超详细)

    lamp的搭建对于初学者是一件很头疼的事情,所以借此机会把自己当初快速搭建linux+apche+mysql+php的方法分享大家希望能到你. 工具/原料 虚拟机及Centos操作系统 Linux基本 ...

  8. destoon 开启邮箱

  9. Java泛型类和泛型方法

    java编程思想说道: 泛型类是应用在整个类上,但同时可以在类中包含参数化方法,而这个方法所在的类可以是泛型,也可以不是泛型,也就是说是否有泛型方法,与其所在的类是否是泛型类没有关系. 泛型方法是的该 ...

  10. oracle01

    01-基本的查询语句 A:一些命令 sqlplus sys/sys@192.168.22.220:1521/orcl as sysdba; conn scott/123456@192.168.22.2 ...