创建线程的方式及实现

  一、继承Thread类创建线程类

    1、定义Thread的子类,并重写run方法,因为该方法的方法体就是代表了线程要完成的任务,因此run方法又叫做执行体。

    2、创建Thread子类的实例,即创建了线程对象。

    3、调用线程对象的start方法来启动该线程。

  二、通过Runnable接口来创建线程类

    1、定义Runnable接口的实现类,并重写run方法,跟Thread一样,该run方法又叫做执行体。

    2、创建实现类的实例,并依此实例作为Thread的target来创建Thread对象,该Thread对象才是真正的对象。

    3、调用线程对象的start方法来启动该线程。

  三、通过Callable和Future创建线程

    1、创建Callable接口的实现类,并实现call()方法,该call()方法将作为线程执行体,并且有返回值。

    2、创建Callable实现类的实例,使用FutureTask类来包装Callable对象,该FutureTask对象封装了该Callable对象的call()方法的返回值。

    3、使用FutureTask对象作为Thread对象的target创建并启动新线程。

    4、调用FutureTask对象的get()方法来获得子线程执行结束后的返回值

  创建线程的三种方式的对比

    采用实现Runnable、Callable接口的方式创见多线程时

    优势是:

      线程类只是实现了Runnable接口或Callable接口,还可以继承其他类。

      在这种方式下,多个线程可以共享同一个target对象,所以非常适合多个相同线程来处理同一份资源的情况,从而可以将CPU、代码和数据分开,形成清晰的模型,较好地体现了面向对象的思想。

    劣势是:

      编程稍微复杂,如果要访问当前线程,则必须使用Thread.currentThread()方法。

    使用继承Thread类的方式创建多线程时优势是:

      编写简单,如果需要访问当前线程,则无需使用Thread.currentThread()方法,直接使用this即可获得当前线程。

    劣势是:

      线程类已经继承了Thread类,所以不能再继承其他父类。

sleep()、join()、yield()区别

  1、sleep()

    在指定毫秒数为单位,让当前正在执行的线程处于休眠状态,但此操作并不会释放对象锁。

  2、yield()

    它与sleep类型,也不会释放锁,但它没有参数,即yield()方法只是使当前线程重新回到可执行状态。该方法只能使同优先级或高优先级的线程得到执行机会,这也和sleep方法不同。 

  3、join()

    Thread的非静态方法join()让一个线程B“加入”到另外一个线程A的尾部。在A执行完毕之前,B不能工作。

sleep()和wait()的区别

  1、对于sleep()方法,我们首先要知道该方法是属于Thread类中的。而wait()方法,则是属于Object类中的

  2、sleep()方法导致了程序暂停执行指定的时间,让出cpu该其他线程,但是他的监控状态依然保持者,当指定的时间到了又会自动恢复运行状态

  3、在调用sleep()方法的过程中,线程不会释放对象锁

  4、而当调用wait()方法的时候,线程会放弃对象锁,进入等待此对象的等待锁定池,只有针对此对象调用notify()方法后本线程才进入对象锁定池准备获取对象锁进入运行状态。

CountDownLatch 原理

  CountDownLatch是同步工具类之一,可以指定一个计数器,在并发环境下由线程进行减1操作,当计数器变为0时,被await方法阻塞的线程将会被唤醒,实现线程间的同步。

CyclicBarrier 原理

  字面意思是可循环(Cyclic)使用的屏障(Barrier)。它要做的事情是让一组线程到达一个屏障(同步点)时被阻塞,直到最后一个线程到达屏障时候,屏障才会开门。所有被屏障拦截的线程才会运行。

说说Semaphore原理

  信号量,用来控制多线程同时访问特定资源时的线程数量,它通过协调合理的使用公共资源。线程通过acquire方法活动信号量的许可,当信号量没有可用的许可的时候,线程阻塞,直到有可用的线程为止。线程可以通过releace方法来释放它持有的信号量许可。

说说 Exchanger 原理

  JDK1.5提供的工具套件,用来处理两个线程之间的数据交换。

ThreadLocal 原理分析

  线程局部变量,并发的时候成员变量是不安全的,因为同时有多个线程在访问,我们需要满足这样一个条件:变量是同一个,但是每个线程都使用同一个初始值,也就是使用同一个变量的一个新的副本,当我们调用get方法的时候,其实每个当前线程中都有一个ThreadLocal。每次获取或者设置都是对该ThreadLocal进行的操作,是与其他线程分开的。

线程池的几种方式

  1、newFixedThreadPool(int nThreads):创建一个固定长度的线程池,每当提交一个任务就创建一个线程,直到达到线程池的最大数量,这时线程的规模将不再变化,当线程发生未预期的错误而结束时,线程池会补充一个新的线程

  2、newCachedThreadPool():创建一个可缓存的线程池,如果线程池超过了处理需求,将自动回收线程池,而当需求增加时,则可以自动添加新线程,线程池的规模不存在任何限制

  3、newSingleThreadExecutor():单线程的Executor,它创建单个工作线程来执行任务,如果这个任务异常结束,会创建一个新的来替代它,它的特点是能确保依照任务在队列中的顺序来串行执行

  4、newScheduledThreadPool(int corePoolSize):创建一个固定长度的线程池,而且以延迟或定时的方式来执行任务,类似于Timer。

线程的生命周期

  新建(new)、就绪(Runnable)、运行(Running)、阻塞(Blockde)、死亡(Dead)

  新建(new Thread):当创建Thread类的实例对象时,此线程进入新建状态(未被启动)

  就绪(Runnable):线程被启动,正在序列队列中等待被分配给CPU资源

  运行(Running):线程获得了CPU资源,正在执行任务(run()方法),运行中除非该线程自动放弃CPU资源或有更高优先级的线程进入,否则它将一直执行下去到任务结束。

  死亡(dead):该线程执行完毕后或被其他线程杀死,线程就进入到了死亡状态,此时线程不可能再进入等待执行状态

  阻塞(Blocked):由于某些原因导致该线程让出CPU并暂停自己的执行。

锁机制

说说线程安全问题

线程安全是指要控制多个线程对某个资源的有序访问或修改,而在这些线程之间没有产生冲突。

线程安全一般体现在两个方面:

  1、多个Thread对同一个实例的访问(read和modify)不会相互干扰,它主要体现在关键字synchronized上。如ArrayList和Vector,HashMap和HashTable(后者每个方法前都有synchronized关键字)

  2、每个线程都有自己的字段,而不会在多个线程之间共享。它主要体现在java.lang.ThreadLocal类,而没有java关键字支持,如static、transient那样。  

悲观锁 乐观锁

悲观锁:总是假设最坏的情况,每次取数据时都认为其他线程会修改,在Java中,synchronized的思想也是悲观锁。

乐观锁:总是认为不会产生并发问题,每次取数据的时候总是认为不会被其他线程修改,但是在更新时会判断其他线程在这之前有没有对数据进行修改,一般会使用版本号机制或CAS操作实现

  1、version方式:一般是在数据表中加上一个数据版本号version字段,表示数据被修改的次数,当数据被修改时,version值会加一。当线程A要更新数据值时,在读取数据的同时也会读取version值,在提交更新时,若刚才读取到的version值为当前数据库中的version值相等时才更新,否则重试更新操作,直到更新成功

  2、CAS操作方式:即compare and swap 或者 compare and set,涉及到三个操作数,数据所在的内存值,预期值,新值。当需要更新时,判断当前内存值与之前取到的值是否相等,若相等,则用新值更新,若失败则重试,一般情况下是一个自旋操作,即不断的重试。  

Java基础知识盘点(三)- 线程篇的更多相关文章

  1. Java基础知识回顾之七 ----- 总结篇

    前言 在之前Java基础知识回顾中,我们回顾了基础数据类型.修饰符和String.三大特性.集合.多线程和IO.本篇文章则对之前学过的知识进行总结.除了简单的复习之外,还会增加一些相应的理解. 基础数 ...

  2. Java基础知识盘点(一)- 基础篇

    基本功 面向对象特征 封装.继承.多态和抽象 1.封装:给对象提供了隐藏内部特性和行为的能力.对象提供一些能被其他对象访问的方法,来改变它内部的数据. 在Java中,其访问权限有3种修饰符:publi ...

  3. Java基础知识盘点(二)- 集合篇

    List和Set区别 List和Set都是继承Collection接口 List特点:元素有放入顺序,元素可重复 Set特点:元素无放入顺序,元素不可重复 Set和List对比: Set:检索元素效率 ...

  4. java 基础知识(三)

    Arraylist与Vector的区别 清浅池塘 程序员,专栏:Java那些事儿唯一作者,咨询前请先点详细资料   162 人赞同了该文章 这几天工作有点忙,有很多代码需要写,更新文章有点慢,说声抱歉 ...

  5. Java基础知识(三)

    一.hashCode 与 equals (重要) 面试官可能会问你:"你重写过 hashcode 和 equals 么,为什么重写equals时必须重写hashCode方法?" 1 ...

  6. JAVA基础知识之多线程——线程池

    线程池概念 操作系统或者JVM创建一个线程以及销毁一个线程都需要消耗CPU资源,如果创建或者销毁线程的消耗源远远小于执行一个线程的消耗,则可以忽略不计,但是基本相等或者大于执行线程的消耗,而且需要创建 ...

  7. JAVA基础知识之多线程——线程通信

    传统的线程通信 Object提供了三个方法wait(), notify(), notifyAll()在线程之间进行通信,以此来解决线程间执行顺序等问题. wait():释放当前线程的同步监视控制器,并 ...

  8. java基础知识总结8(数据库篇1)

    一. Oracle的安装(windowXP.win7.Linux)和卸载 1.1 Oracle的安装 1.1.1 在WindowsXP.Win7下安装 第一:解压win32_11gR2_databas ...

  9. java基础知识(三)java关键字

    关键字是电脑语言事先定义的,是特别意义的标识符,又叫保留字.用来表示一种数据类型或程序的结构等,关键字不能用作变量名.类名.方法名或参数.java目前共有50个关键字,其中"const&qu ...

随机推荐

  1. centOS 7 设置DNS方法 同之前版本不同

    在CentOS 7下,手工设置 /etc/resolv.conf 里的DNS,过了一会,发现被系统重新覆盖或者清除了.和CentOS 6下的设置DNS方法不同,有几种方式: 1.使用全新的命令行工具 ...

  2. MongoDB3.2新特性之部分索引

    官方介绍:https://docs.mongodb.org/manual/core/index-partial/ mongodb3.2支持对某个集合的部分数据创建索引.如给年龄大于十八岁的数据创建索引 ...

  3. MySql数据库中,判断表、表字段是否存在,不存在就新增

    本文是针对MySql数据库创建的SQL脚本,别搞错咯. 判断表是否存在,不存在就可新增 CREATE TABLE IF NOT EXISTS `mem_cardtype_resource` ( ... ...

  4. gdb调试android

    手机端 adb shell gdbserver  --mulit *:23333 /data/local/tmp/test 电脑 target  remote 192.168.1.170:23333

  5. 运维自动化之系统部署 PXE(二)

    PXE介绍 Preboot Excution Environment 预启动执行环境 Intel公司研发 基于Client/Server的网络模式,支持远程主机通过网络从远端服务器下载映像,并由此支持 ...

  6. Google word/sheets 常见的使用:

    Google Sheets: 1, sheets 里面的单元格设置自动换行: 选中单元格: --> Format --> Text Wrapping --> Wrap(自动换行)/C ...

  7. appium 环境搭建2

    以windows-x64为例安装的软件有JDK  AndriodSDK   Node.js   Appium(界面化的可以不装)   python  Appium_Python_Client.安装的顺 ...

  8. 接口自动化测试持续集成--Soapui接口功能测试断言

    断言也就是判断实际结果与预期结果是否相等,如果相等测试通过,否则测试失败,自动化测试不管是UI,Services还有unit都需要做断言. 一.添加断言步骤的组件 二.设置断言 设置常用断言的三种方式 ...

  9. 2019春下载的sublime text都无法自动安装package control:解决办法

    之前电脑的原因卸载了,于是重新安装sublime text3. 发现问题了.Package Control无法自动安装. 于是一通常用操作. 1.copy 安装码(你知道的)到control安装,失败 ...

  10. SQL注入检测方法

    private bool CheckParams(params object[] args){ string[] Lawlesses={"=","'"}; if ...