写在多线程学习之前

  打算在每个专题的学习之前,写一篇随笔,记录下自己对该专题认知的1.0版,以后持续迭代。我学习多线程有以下两个原因:

  一、多线程是高级开发人员必备的技能,我对多线程可以说仍是一知半解,停留在零散理论阶段,未达到系统理论阶段,更未达到实战阶段。工作中接触到线程有三次,现在总结才发现都和定时任务有关,看来定时任务是多线程使用率比较高的一个场景。

    1、在第一家公司,写了一个简单的单线程用于同步数据。

    2、在第二家公司,用到公司封装好的定时任务框架,当时觉得到封装底层肯定是用到了线程,现在想想还用到了线程池。

    3、最近到了新单位又是一个定时任务的需求,定时同步数据给企业微信号,为了支持cron表达式的数据库可配置,支持该定时模块以后的可扩展,选择了一个轻量级的Quartz——Spring Task,其底层实现也是维护了一个线程池。目前这个小小的定时模块已经实现了,但是却勾起了我学习多线程的兴趣,不能一直停留在应用层面,必须深入底层,知其然,并知其所以然。

  说到这说一个题外话,以前做开发,时间非常紧迫,每次都是奔着快速完成任务,没有时间去比较哪种方式好,没有时间去了解技术的底层,对个人的成长来说是不利的,尤其是对一些只能涉及一些业务层面开发的技术人员,除非自己有强烈的求知欲,但也得有那个精力不是。

   二、曾经在好几次的面试中被问及了Java线程相关的问题,自己的回答总是不尽如人意,并且每次都会有新的问题出现,以下列举下自己遇到的线程的面试问题,在以后的学习中逐个解开疑团。

  1、Java线程的实现方式

   大家都知道的有两种继承Thread类或者实现Runable接口,有一次面试被问说还有一种方式,当然是不知道,后来自己查是实现Callable<T>接口,实现Callable<T>接口的线程是有返回值的。本质不是要记住这些方式,而是知道在什么情况用。

   2、Java线程提供的方法

   run()方法和start()方法,run()方法用于实现线程的任务,start()方法用于启动线程,run方法和普通的Java方法没有本质区别。可能是因为一些面试中总是问到这两个方法的区别,反而让一些初学者有些混淆了。还有Thread类的其它一些,如sleep()、join()、yield()等,还有Object类的wait()、notify/notifyAll() 方法。这些方法中除了run()方法,其它方法都是通过JNI调用了操作系统对应的线程操作方法。

  3、线程的同步,线程安全

  以前在写业务代码的时候,遇到需要互斥访问的代码块,会用到synchronized,synchronized的本质就是加锁,只是这个锁不用开发者自己加自己解,锁有对象锁和类锁。volatile我在实际开发中没有用到过,是在一次面试中被问到,后来特意查了一下,volatile可以实现线程对变量的可见性,但是不保证原子性,但在特定场景下还是很有用的,汗颜啊!另外还有Java提供的原子类如AtomicLong、AtomicInteger等。还有一些其它的线程同步方法,后面会详细学习比较。

  4、线程池

    线程池以前在工作中没写过,但其实平时工作中一直都站在巨人的肩膀上,有意无意的享用着线程池,如数据库连接池、Tomca线程池,Java线程池相关实现在Java SDK并发包concurrent中,包括Executor、Executors、ExecutorService等,了解了一下并发包concurrent是并发大师Doug Lea设计的,是Java1.5的特性,作为一个Java开发者,膜拜下。

  以上是我对多线程的所知所想,属于是跳出来看全局吧,后面准备钻进去看本质,期待自己在多线程编程上能持续深耕,有质的突破。

 

posted @ 2019-06-21 17:44  cblpolly  阅读(185)  评论(0编辑  收藏  举报