Java中多线程的实现方式

在java的历史版本中,有两种创建多线程程序的方法

1) 通过创建Thread类的子类来实现(Thread类提供了主线程调用其它线程并行运行的机制)

主要步骤:

自定义类继承Thread类,然后覆盖其中的run方法,使得该线程能够完成特定的工作,使用start方法启动线程,将执行权转交到run.

2) 通过实现Runable接口的类来实现(推荐,可以实现数据共享,而且可以避免因为类单继承的局限)

主要步骤:

a>. 创建某个类实现Runnable接口,实现run()方法。

b>. 创建Thread对象,用实现Runnable接口的对象作为参数实例化该Thread对象。

c>. 调用Thread的start方法。

说明:

Thread是一个类,而Runnable是一个接口.

JAVA线程控制着程序执行的主路径;当你用java命令调用JVM时,JVM创建了一个隐式线程来执行main方法.

3) 在JDK5.0后,使用Executor框架管理线程.

虽然可以使用Thread类来显示的创建线程,但推荐的做法是使用Executor接口,让它来管理Runnable对象的执行.

通常Executor对象会创建并管理一组执行Runnable对象的线程,这组线程被称为线程池,Executor基于生产者-消费者模式.提交任务的执行者是生产者(产生待完成的工作单元),执行任务的线程是消费者(消耗掉这些工作单元)

采用Executor的优势

a) Executor对象能够复用已有的线程,从而消除了为每个任务创建新线程的开销,

b) 它能通过优化线程的数量,提高程序性能,保证处理器一直处于忙碌状,而不必创建过多的线程使程序资源耗尽。

Executor接口的定义[JDK源码引入]

public interface Executor{void execute(Runnable command); }

ExecutorService接口[JDK源码引入]

public interface ExecutorService extends Executor {void shutdown(); List<Runnable> shutdownNow(); boolean isShutdown(); boolean isTerminated(); boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException; <T> Future<T> submit(Callable<T> task); <T> Future<T> submit(Runnable task, T result); Future<?> submit(Runnable task); <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks) throws InterruptedException; <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit) throws InterruptedException; <T> T invokeAny(Collection<? extends Callable<T>> tasks) throws InterruptedException, ExecutionException; <T> T invokeAny(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException; }

ExecutorService暗示了生命周期的3种状态:运行(running)、关闭(shutting down)和终止(terminated).
ExecutorService最初创建后的初始状态是运行状态.shutdown方法会启动一个平缓的关闭过程:停止接受新的任务,同时等待已经提交的任务完成-包括尚未开始执行的任务. shutdownNow方法会启动一个强制关闭过程,尝试取消所有运行中的任务和排在队列中尚未开始的任务.在关闭后提交到ExecutorService的任务会抛出RejectedExecution异常.

Executors类,该类是一个独立类,提供一系列灵活的线程池实现和一些有用的预设配置.[JDK源码引入]

public class Executors {public static ExecutorService newFixedThreadPool(int nThreads) { return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>()); } ... ... }

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

public static ExecutorService newFixedThreadPool(int nThreads)
创建固定数目线程的线程池,每当提交一个任务就创建一个线程,直到达到池的最大长度,这时线程池会保持长度不再变化.
public static ExecutorService newCachedThreadPool() 创建一个可缓存的线程池,调用execute 将重用以前构造的线程(如果线程可用)。如果现有线程没有可用的,则创建一个新线程并添加到池中。终止并从缓存中移除那些已有 60 秒钟未被使用的线程。 public static ExecutorService newSingleThreadExecutor() 创建一个单线程化的Executor,它只创建唯一的工作者线程来执行任务,如果这个线程异常结束,会有另一个取代它. public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) 创建定长线程池,支持定时及周期性的任务执行,多数情况下可用来替代Timer类。

新线程实例应用
使用新线程实现一个无返回的线程实例

public class ThreadPoolTest {public static void main(String[] args) { //使用动态缓存线程池,池中的线程随着任务数量的变化而变化 ExecutorService threadPool = Executors.newCachedThreadPool(); //循环产生5个任务丢给线程池 for(int i=1; i<=5; i++){ final int taskNum = i; threadPool.execute(new Runnable() { @Override public void run() { for(int j=1; j<=2; j++){ try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("任务[" + taskNum + "]使用线程[" + Thread.currentThread().getName() + "]循环打印数据:" + j); } } });//end execute(..); }//end for(var i) //如果线程中任务执行完毕,没有任务需要执行了,就关闭线程池,如果不关闭,程序就不会结束,而是持续等待新的任务.  threadPool.shutdown(); } }

传统的实现方式以及上面的线程实现方式都不可能有返回值.在ExecutorService中定义了系列的submit(xxx)方法,该方法可以返回Future<V>接口,通过调用其V get() throws InterruptedException, ExecutionException;就可以获取到线程执行结果.submit可以传滴一个Runnable接口的实现类,也可以传递一个Callable接口的实现类.
Callable接口的实现类[JDK源码引入]

public interface Callable<V> {V call() throws Exception; }

说明:Future<V>代表一个异步执行的操作,通过get()方法可以获得操作的结果,如果异步操作还没有完成,则get()会使当前线程阻塞,直到计算完成.

编写5.0新线程的步骤

1.先写一个Callable的子类,然后实现call()方法.

2.调用Executors.newXXThreadPool()返回ExecutorService类型.

3.调用ExecutorService中的submit(Callable的子类)方法启动线程.

4.只有调用ExecutorService的shutdown()方法才能真正的离开虚拟机.

import java.util.concurrent.*;public class ExecutorTest implements Callable { @SuppressWarnings("unchecked") public static void main(String[] args) throws Exception { //创建缓存线程池 ExecutorService pool = Executors.newCachedThreadPool(); //指定线程,获取线程返回结果 Future returnV = pool.submit(new ExecutorTest()); //获取线程返回结果 System.out.println("" + returnV.get().toString()); //关闭线程池  pool.shutdown(); } @Override public Object call() throws Exception { for(int i=1; i<=5; i++){ Thread.sleep (500); System.out .println(Thread.currentThread().getName()+" print value " +i); } return "Multiple Thread Implements Callable"; } }

该接口扩展了Executor接口,并声明了许多方法用于管理Executor的声明周期

转载请注明出处:[http://www.cnblogs.com/dennisit/p/3690378.html]

热爱生活,热爱Coding,敢于挑战,用于探索 ...

转载于:https://www.cnblogs.com/jianmang/articles/4879040.html

面试求职中需要了解的Java多线程知识相关推荐

  1. 如何应对面试官:什么场景中会用到java多线程?

    如何应对面试官:什么场景中会用到java多线程? 作者:云栖社区 原文:https://yq.aliyun.com/ziliao/1765 (点击文末阅读原文即可前往) 问:能不能简单描述一下你在ja ...

  2. Interview:Java岗位面试—面试求职攻略之一个JAVA程序员面试心得(非常值得收藏)

    Interview:Java岗位面试-面试求职攻略之一个JAVA程序员面试心得(非常值得收藏) 导读 据网上资料显示:2018年互联网行业是寒冬,其他行业日子也不好过.各个互联网大厂纷纷缩招减员,严格 ...

  3. 面试姊妹篇4:常见的Java多线程面试题

    主要内容 本文主要记录多线程相关的操作问题,这些问题主要出现在一些面试中,当然学会了对本身的代码能力也有提升. 目录 1.交替多线程 2.发令枪问题 3.多线程顺序执行 4.关于饥饿死锁 5.线程数设 ...

  4. Java多线程知识小抄集(四)——完结

    欢迎支持笔者新作:<深入理解Kafka:核心设计与实践原理>和<RabbitMQ实战指南>,同时欢迎关注笔者的微信公众号:朱小厮的博客. 欢迎跳转到本文的原文链接:https: ...

  5. Java多线程知识小抄集(三)

    欢迎支持笔者新作:<深入理解Kafka:核心设计与实践原理>和<RabbitMQ实战指南>,同时欢迎关注笔者的微信公众号:朱小厮的博客. 欢迎跳转到本文的原文链接:https: ...

  6. Java多线程知识小抄集(二)

    欢迎支持笔者新作:<深入理解Kafka:核心设计与实践原理>和<RabbitMQ实战指南>,同时欢迎关注笔者的微信公众号:朱小厮的博客. 欢迎跳转到本文的原文链接:https: ...

  7. Java多线程知识小抄集(一)

    欢迎支持笔者新作:<深入理解Kafka:核心设计与实践原理>和<RabbitMQ实战指南>,同时欢迎关注笔者的微信公众号:朱小厮的博客. 欢迎跳转到本文的原文链接:https: ...

  8. 多线程java_初学Java要注意什么 怎么掌握Java多线程知识

    初学Java要注意什么?怎么掌握Java多线程知识?很多初学Java的同学通常会对进程和线程傻傻分不清,进程和线程都是由操作系统所体会的程序运行的基本单元,一个程序至少有一个进程,一个进程至少有一个线 ...

  9. 面试求职中遇到的那些问题

    面试中的那些"送命题" 你中招了吗? 微博:@恺思ZKN 丰经允许勿二改二传 客素引 口L.最简单也是最雅的"自背f招 己,内什么想开们公司工作? 口彐.施爪是字囗专业的 ...

最新文章

  1. autohotkey快捷键
  2. 22w+的人选择了这款蓝牙耳机
  3. 拦截导弹(最长递增子序列)
  4. C++中一个容易被忽视的名字查找规则
  5. poj 2342 树形DP
  6. Spring@主要注释
  7. 代码注释: (文字图案:HIRE)
  8. Linux zip命令:压缩文件或目录
  9. Python统计多个Powerpoint文件中幻灯片总数量
  10. C#使用Windows Service
  11. 阶段1 语言基础+高级_1-3-Java语言高级_09-基础加强_第2节 反射_7_反射_Class对象功能概述...
  12. Unity的包体压缩以及音效优化
  13. 2022Java微服务最全面试题集
  14. Unity3D逻辑热更新,第二代舒爽解决方案,L#使用简介
  15. 调用企查查上的接口,实现通过公司名称查询公司列表
  16. signature=5a537e48de3abe15561f136edabc54dc,Visual Signatures in Video Visualization
  17. 【荐书】李彦宏《智能革命》:技术是时代的信仰
  18. 《点燃我,温暖你》爱心代码复现
  19. 卷积神经网络demo
  20. OPENSSL EVP_AES部分翻译

热门文章

  1. 播放音乐的html语言,Html5音频和视频播放示例详解
  2. 罗盘时钟制作代码_抖音八卦时钟手机屏保设置方法!
  3. 【JavaScript】【ChormeDav】问卷星自动填写问卷
  4. 第一章节 初识C#程序
  5. vc 控制台添加托盘显示_VC添加托盘图标
  6. select默认选中的option_技巧:MacOS 中 Option 键的隐藏功能
  7. 试题7 算法训练 P0505(最右边的那个非0的数字)
  8. Unity3D 拆包工具 AssetStudio 编译构建
  9. 2017 ACM-ICPC乌鲁木齐网络赛 G. Query on a string(KMP+树状数组)
  10. 教程:Visual Studio 连接 MySQL 数据库(包含常见错误及解决方法)