创建线程的方式及实现

  一、继承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. 2016(4)数据库系统,ER模型,规范化理论,并发控制

    试题四(共25分) 阅读以下关于数据库设计的叙述,在答题纸上回答问题1至问题3. 某航空公司要开发一个订票信息处理系统,以方便各个代理商销售机票.开发小组经过设计,给出该系统的部分关系模式如下: 航班 ...

  2. 学号 20175201张驰 《Java程序设计》第4周学习总结

    学号 20175201张驰 <Java程序设计>第4周学习总结 教材学习内容总结 第5章 继承:避免多个类间重复定义共同行为,用我们已经有的类,去创建新的类 任何子类都可以继承它的父类的成 ...

  3. 最好还是用#pragma once

    最好还是用#pragma once  https://www.cnblogs.com/techdreaming/p/4921780.html

  4. ESP8266 RTOS SDK烧写环境构建

    简介 esptool是一个Python软件程序,适用于ESP8266等一系列芯片的烧写,灵活高效. 环境构建 在官网下载安装最新2.7版python (linux和os x一般会自带python2.7 ...

  5. java的智能提示无法打开

    第一步:选中“window”->“preference”   第二步:选中“java”,并展开   第三步:选中“Editor”,并展开   第四步:选中“Content Assist”,在右侧 ...

  6. c#十进制转二进制算法 和字符串反转算法

    去某软面试 面试官给个题上黑板做,写个算法 求95转2进制后1的个数. 我在黑板上敲了 static int count = 0; /// <summary> /// 获取10进制数转2进 ...

  7. 【论文速读】Dan_Deng_AAAI2018_PixelLink_Detecting_Scene_Text_via_Instance_Segmentation

    Dan Deng--[AAAI2018]PixelLink_Detecting Scene Text via Instance Segmentation 作者和代码 tensorflow代码 关键词 ...

  8. 2015年上海现场赛重现 (A几何, K暴力搜索)

    A: 题目链接 :https://vjudge.net/contest/250823#problem/A 参考 : https://www.cnblogs.com/helenawang/p/54654 ...

  9. CentOS6.5 切换 图形界面 与 命令行界面

    CentOS6.5 切换图形界面与命令行界面 [1]场景1:图形界面 -> 命令行界面 方式一(快捷键):Ctrl + Alt + F2 方式二(终端命令):init 3 (PS:init与3之 ...

  10. Oarcle之group by关键字与having关键字

    group by关键字    *group by :分组由 作用: 用于对于查询的数据进行分组并进行处理 例如:select deptno ,job from emp group by deptno, ...