Java多线程实现四种方式原理详解


Posted in Python onJune 02, 2020

1.继承Thread类,重写run方法

2.实现Runnable接口,重写run方法,实现Runnable接口的实现类的实例对象作为Thread构造函数的target

3.通过Callable和FutureTask创建线程

4.通过线程池创建线程

前面两种可以归结为一类:无返回值,原因很简单,通过重写run方法,run方式的返回值是void,所以没有办法返回结果

后面两种可以归结成一类:有返回值,通过Callable接口,就要实现call方法,这个方法的返回值是Object,所以返回的结果可以放在Object对象中

1. 继承Thread类

public class ThreadDemo01 extends Thread{
  public ThreadDemo01(){
    //编写子类的构造方法,可缺省
  }
  public void run(){
    //编写自己的线程代码
    System.out.println(Thread.currentThread().getName());
  }
  public static void main(String[] args){ 
    ThreadDemo01 threadDemo01 = new ThreadDemo01(); 
    threadDemo01.setName("我是自定义的线程1");
    threadDemo01.start();    
    System.out.println(Thread.currentThread().toString()); 
  }
}

程序结果:

Thread[main,5,main]
我是自定义的线程1

2. 实现Runnable接口

重写run方法,接口的实现类的实例作为Thread的target作为参数传入带参的Thread构造函数,通过调用start()方法启动线程

public class ThreadDemo02 {
  public static void main(String[] args){ 
    System.out.println(Thread.currentThread().getName());
    Thread t1 = new Thread(new MyThread());
    t1.start(); 
  }
}

class MyThread implements Runnable{
  @Override
  public void run() {
    // TODO Auto-generated method stub
    System.out.println(Thread.currentThread().getName()+"-->我是通过实现接口的线程实现方式!");
  }  
}

程序运行结果:

main
Thread-0?>我是通过实现接口的线程实现方式!

3. 通过Callable和FutureTask创建线程

  • 创建Callable接口的实现类 ,并实现Call方法
  • 创建Callable实现类的实现,使用FutureTask类包装Callable对象,该FutureTask对象封装了Callable对象的Call方法的返回值
  • 使用FutureTask对象作为Thread对象的target创建并启动线程
  • 调用FutureTask对象的get()来获取子线程执行结束的返回值
public class ThreadDemo03 {
  /**
   * @param args
   */
  public static void main(String[] args) {
    // TODO Auto-generated method stub
    Callable<Object> oneCallable = new Tickets<Object>();
    FutureTask<Object> oneTask = new FutureTask<Object>(oneCallable);
    Thread t = new Thread(oneTask);
    System.out.println(Thread.currentThread().getName());
    t.start();
  }
}
class Tickets<Object> implements Callable<Object>{

  //重写call方法
  @Override
  public Object call() throws Exception {
    // TODO Auto-generated method stub
    System.out.println(Thread.currentThread().getName()+"-->我是通过实现Callable接口通过FutureTask包装器来实现的线程");
    return null;
  }  
}

程序运行结果:

main
Thread-0?>我是通过实现Callable接口通过FutureTask包装器来实现的线程

4. 通过线程池创建线程

public class ThreadDemo05{
  private static int POOL_NUM = 10;   //线程池数量

  /**
   * @param args
   * @throws InterruptedException 
   */
  public static void main(String[] args) throws InterruptedException {
    // TODO Auto-generated method stub
    ExecutorService executorService = Executors.newFixedThreadPool(5); 
    for(int i = 0; i<POOL_NUM; i++) { 
      RunnableThread thread = new RunnableThread();
      //Thread.sleep(1000);
      executorService.execute(thread); 
    }
    //关闭线程池
    executorService.shutdown(); 
  }  
}

class RunnableThread implements Runnable {   
  @Override
  public void run() { 
    System.out.println("通过线程池方式创建的线程:" + Thread.currentThread().getName() + " "); 
  } 
}

程序运行结果:

通过线程池方式创建的线程:pool-1-thread-3
通过线程池方式创建的线程:pool-1-thread-4
通过线程池方式创建的线程:pool-1-thread-1
通过线程池方式创建的线程:pool-1-thread-5
通过线程池方式创建的线程:pool-1-thread-2
通过线程池方式创建的线程:pool-1-thread-5
通过线程池方式创建的线程:pool-1-thread-1
通过线程池方式创建的线程:pool-1-thread-4
通过线程池方式创建的线程:pool-1-thread-3
通过线程池方式创建的线程:pool-1-thread-2

ExecutorService、Callable都是属于Executor框架。还有Future接口也是属于这个框架,有了这种特征得到返回值就很方便了。
通过分析可以知道,他同样也是实现了Callable接口,实现了Call方法,所以有返回值。这也就是正好符合了前面所说的两种分类
执行Callable任务后,可以获取一个Future的对象,在该对象上调用get就可以获取到Callable任务返回的Object了。get方法是阻塞的,即:线程无返回结果,get方法会一直等待。

Executors类:提供了一系列工厂方法用于创建线程池,返回的线程池都实现了ExecutorService接口。

// 创建固定数目线程的线程池
public static ExecutorService newFixedThreadPool(int nThreads)

// 创建一个可缓存的线程池,调用execute 将重用以前构造的线程(如果线程可用)。如果现有线程没有可用的,则创建一个新线程并添加到池中。终止并从缓存中移除那些已有 60 秒钟未被使用的线程
public static ExecutorService newCachedThreadPool()

// 创建一个单线程化的Executor
public static ExecutorService newSingleThreadExecutor()

// 创建一个支持定时及周期性的任务执行的线程池,多数情况下可用来替代Timer类
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize)

ExecutoreService提供了submit()方法,传递一个Callable,或Runnable,返回Future。

如果Executor后台线程池还没有完成Callable的计算,这调用返回Future对象的get()方法,会阻塞直到计算完成。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
Python字符串的encode与decode研究心得乱码问题解决方法
Mar 23 Python
使用Python导出Excel图表以及导出为图片的方法
Nov 07 Python
举例讲解Python中metaclass元类的创建与使用
Jun 30 Python
python 爬虫出现403禁止访问错误详解
Mar 11 Python
在Python 2.7即将停止支持时,我们为你带来了一份python 3.x迁移指南
Jan 30 Python
matplotlib.pyplot画图 图片的二进制流的获取方法
May 24 Python
python中如何使用分步式进程计算详解
Mar 22 Python
python适合人工智能的理由和优势
Jun 28 Python
Python实现决策树并且使用Graphviz可视化的例子
Aug 09 Python
Python爬虫之urllib基础用法教程
Oct 12 Python
解决pycharm导入numpy包的和使用时报错:RuntimeError: The current Numpy installation (‘D:\\python3.6\\lib\\site-packa的问题
Dec 08 Python
Pytorch之扩充tensor的操作
Mar 04 Python
Python+Kepler.gl轻松制作酷炫路径动画的实现示例
Jun 02 #Python
opencv+python实现鼠标点击图像,输出该点的RGB和HSV值
Jun 02 #Python
简单介绍一下pyinstaller打包以及安全性的实现
Jun 02 #Python
Python几种常见算法汇总
Jun 02 #Python
opencv-python的RGB与BGR互转方式
Jun 02 #Python
解决pyinstaller打包运行程序时出现缺少plotly库问题
Jun 02 #Python
Pytorch 使用opnecv读入图像由HWC转为BCHW格式方式
Jun 02 #Python
You might like
PHP读取、解析eml文件及生成网页的方法示例
2017/09/04 PHP
Bootstrap+PHP实现多图上传功能实例详解
2018/04/08 PHP
PHP实现数组根据某个单元字段排序操作示例
2018/08/01 PHP
Mac下快速搭建PHP开发环境步骤详解
2019/05/05 PHP
Laravel第三方包报class not found的解决方法
2019/10/13 PHP
利用jQuery插件扩展识别浏览器内核与外壳的类型和版本的实现代码
2011/10/22 Javascript
浅析jQuery中常用的元素查找方法总结
2013/07/04 Javascript
导航跟随滚动条置顶移动示例代码
2013/09/11 Javascript
快速解决jQuery与其他库冲突的方法介绍
2014/01/02 Javascript
jQuery入门介绍之基础知识
2015/01/13 Javascript
JavaScript与HTML的结合方法详解
2015/11/23 Javascript
AngularJS中如何使用$http对MongoLab数据表进行增删改查
2016/01/23 Javascript
jQuery实现最简单的切换图效果【可兼容IE6、火狐、谷歌、opera等】
2016/09/04 Javascript
自己封装的一个简单的倒计时功能实例
2016/11/23 Javascript
BootStrap table删除指定行的注意事项(笔记整理)
2017/02/05 Javascript
javascript编写简易计算器
2017/05/06 Javascript
小程序兼容安卓和IOS数据处理问题及坑
2018/09/18 Javascript
JavaScript中的回调函数实例讲解
2019/01/27 Javascript
python3.3实现乘法表示例
2014/02/07 Python
Python升级导致yum、pip报错的解决方法
2017/09/06 Python
Python引用传值概念与用法实例小结
2017/10/07 Python
pycharm+django创建一个搜索网页实例代码
2018/01/24 Python
Centos7 Python3下安装scrapy的详细步骤
2018/03/15 Python
python ---lambda匿名函数介绍
2019/03/13 Python
Python read函数按字节(字符)读取文件的实现
2019/07/03 Python
Python求两个字符串最长公共子序列代码实例
2020/03/05 Python
Python小白学习爬虫常用请求报头
2020/06/03 Python
英国著名的药妆网站:Escentual
2016/07/29 全球购物
Fashion Eyewear美国:英国线上设计师眼镜和太阳镜的零售商
2016/08/15 全球购物
餐厅执行经理岗位职责范本
2014/02/26 职场文书
公司联欢晚会主持词
2014/03/22 职场文书
团结就是力量演讲稿
2014/05/21 职场文书
小学感恩教育活动总结
2014/07/07 职场文书
国庆节促销广告语2014
2014/09/19 职场文书
同学会邀请函模板
2015/01/30 职场文书
如何用JavaScript实现一个数组惰性求值库
2021/05/05 Javascript