学习之前,先了解线程状态图

说明
线程共包括以下5种状态。
  1. 新建状态(New)         : 线程对象被创建后,就进入了新建状态。例如,Thread thread = new Thread()。
  2. 就绪状态(Runnable): 也被称为“可执行状态”。线程对象被创建后,其它线程调用了该对象的start()方法,从而来启动该线程。例如,thread.start()。处于就绪状态的线程,随时可能被CPU调度执行。
  3. 运行状态(Running) : 线程获取CPU权限进行执行。需要注意的是,线程只能从就绪状态进入到运行状态。
  4. 阻塞状态(Blocked): 阻塞状态是线程因为某种原因放弃CPU使用权,暂时停止运行。直到线程进入就绪状态,才有机会转到运行状态。阻塞的情况分三种:
      (01) 等待阻塞 -- 通过调用线程的wait()方法,让线程等待某工作的完成。
      (02) 同步阻塞 -- 线程在获取synchronized同步锁失败(因为锁被其它线程所占用),它会进入同步阻塞状态。
      (03) 其他阻塞 -- 通过调用线程的sleep()或join()或发出了I/O请求时,线程会进入到阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入就绪状态。
  5. 死亡状态(Dead): 线程执行完了或者因异常退出了run()方法,该线程结束生命周期。


常用的实现多线程的两种方式

  1. 实现Runnable接口;

  2. 继承Thread类。

Thread和Runnable的异同点:

  Thread 和 Runnable 的相同点:都是“多线程的实现方式”。
  Thread 和 Runnable 的不同点:Thread 是类,而Runnable是接口;Thread本身是实现了Runnable接口的类。我们知道“一个类只能有一个父类,但是却能实现多个接口”,因此Runnable具有更好的扩展性。
                 此外,Runnable还可以用于“资源的共享”。即,多个线程都是基于某一个Runnable对象建立的,它们会共享Runnable对象上的资源。
  通常,建议通过“Runnable”实现多线程!


Thread中start()和run()的区别

  start() : 它的作用是启动一个新线程,新线程会执行相应的run()方法。start()不能被重复调用。
  run()   : run()就和普通的成员方法一样,可以被重复调用。单独调用run()的话,会在当前线程中执行run(),而并不会启动新线程!


synchronized关键字

原理

在java中,每一个对象有且仅有一个同步锁。这也意味着,同步锁是依赖于对象而存在。
当我们调用某对象的synchronized方法时,就获取了该对象的同步锁。例如,synchronized(obj)就获取了“obj这个对象”的同步锁。
不同线程对同步锁的访问是互斥的。

基本规则

第一条: 当一个线程访问“某对象”的“synchronized方法”或者“synchronized代码块”时,其他线程对“该对象”的该“synchronized方法”或者“synchronized代码块”的访问将被阻塞。
第二条: 当一个线程访问“某对象”的“synchronized方法”或者“synchronized代码块”时,其他线程仍然可以访问“该对象”的非同步代码块
第三条: 当一个线程访问“某对象”的“synchronized方法”或者“synchronized代码块”时,其他线程对“该对象”的其他的“synchronized方法”或者“synchronized代码块”的访问将被阻塞。

实例锁 和 全局锁

实例锁 -- 锁在某一个实例对象上。如果该类是单例,那么该锁也具有全局锁的概念。
               实例锁对应的就是synchronized关键字。
全局锁 -- 该锁针对的是类,无论实例多少个对象,那么线程都共享该锁。
               全局锁对应的就是static synchronized(或者是锁在该类的class或者classloader对象上)。

关于“实例锁”和“全局锁”有一个很形象的例子:

pulbic class Something {
public synchronized void isSyncA(){}
public synchronized void isSyncB(){}
public static synchronized void cSyncA(){}
public static synchronized void cSyncB(){}
}
###############
假设,Something有两个实例x和y。分析下面4组表达式获取的锁的情况。
(01) x.isSyncA()与x.isSyncB()
  不能被同时访问。因为isSyncA()和isSyncB()都是访问同一个对象(对象x)的同步锁!
(02) x.isSyncA()与y.isSyncA()
  可以同时被访问。因为访问的不是同一个对象的同步锁,x.isSyncA()访问的是x的同步锁,而y.isSyncA()访问的是y的同步锁
(03) x.cSyncA()与y.cSyncB()
  不能被同时访问。因为cSyncA()和cSyncB()都是static类型,x.cSyncA()相当于Something.isSyncA(),y.cSyncB()相当于Something.isSyncB(),因此它们共用一个同步锁不能被同时访问
(04) x.isSyncA()与Something.cSyncA()
  可以被同时访问。因为isSyncA()是实例方法,x.isSyncA()使用的是对象x的锁;而cSyncA()是静态方法,Something.cSyncA()可以理解对使用的是“类的锁”。因此,它们是可以被同时访问的。

感谢:https://www.cnblogs.com/skywang12345/p/java_threads_category.html

java多线程中篇(二) —— 线程的创建和Synchronized锁关键字的更多相关文章

  1. Java多线程并发01——线程的创建与终止,你会几种方式

    本文开始将开始介绍 Java 多线程与并发相关的知识,多谢各位一直以来的关注与支持.关注我的公众号「Java面典」了解更多 Java 相关知识点. 线程的创建方式 在 Java 中,用户常用的主动创建 ...

  2. Java多线程学习(二)---线程创建方式

    线程创建方式 摘要: 1. 通过继承Thread类来创建并启动多线程的方式 2. 通过实现Runnable接口来创建并启动线程的方式 3. 通过实现Callable接口来创建并启动线程的方式 4. 总 ...

  3. Java多线程并发02——线程的生命周期与常用方法,你都掌握了吗

    在上一章,为大家介绍了线程的一些基础知识,线程的创建与终止.本期将为各位带来线程的生命周期与常用方法.关注我的公众号「Java面典」了解更多 Java 相关知识点. 线程生命周期 一个线程不是被创建了 ...

  4. Java多线程系列--“JUC线程池”03之 线程池原理(二)

    概要 在前面一章"Java多线程系列--“JUC线程池”02之 线程池原理(一)"中介绍了线程池的数据结构,本章会通过分析线程池的源码,对线程池进行说明.内容包括:线程池示例参考代 ...

  5. -1-5 java 多线程 概念 进程 线程区别联系 java创建线程方式 线程组 线程池概念 线程安全 同步 同步代码块 Lock锁 sleep()和wait()方法的区别 为什么wait(),notify(),notifyAll()等方法都定义在Object类中

     本文关键词: java 多线程 概念 进程 线程区别联系 java创建线程方式 线程组 线程池概念 线程安全 同步 同步代码块 Lock锁  sleep()和wait()方法的区别 为什么wait( ...

  6. Java多线程(三)如何创建线程

    点我跳过黑哥的卑鄙广告行为,进入正文. Java多线程系列更新中~ 正式篇: Java多线程(一) 什么是线程 Java多线程(二)关于多线程的CPU密集型和IO密集型这件事 Java多线程(三)如何 ...

  7. Java多线程系列--“JUC线程池”06之 Callable和Future

    概要 本章介绍线程池中的Callable和Future.Callable 和 Future 简介示例和源码分析(基于JDK1.7.0_40) 转载请注明出处:http://www.cnblogs.co ...

  8. Java多线程系列--“JUC线程池”04之 线程池原理(三)

    转载请注明出处:http://www.cnblogs.com/skywang12345/p/3509960.html 本章介绍线程池的生命周期.在"Java多线程系列--“基础篇”01之 基 ...

  9. Java多线程系列--“JUC线程池”05之 线程池原理(四)

    概要 本章介绍线程池的拒绝策略.内容包括:拒绝策略介绍拒绝策略对比和示例 转载请注明出处:http://www.cnblogs.com/skywang12345/p/3512947.html 拒绝策略 ...

随机推荐

  1. mysql数据库出现无法登录(ERROR 1045 ),预防和解决及系列问题解决方法。

      一 .当在windows下使用mysql数据库时,出现无法登录的现象,需要修改mysql数据库的roo密码时,我们可以使用一下两种方法. 1. (1)关闭mysql服务.然后在bin目录下使用cm ...

  2. Spring boot RSA 文件加密解密

    github项目地址 rsa_demo ##测试 加密D:/hello/test.pdf 文件,生成加密后的文件 testNeedDecode.pdf 对testNeedDecode.pdf 文件进行 ...

  3. 使用清华源 tensorflow 安装

    1. 超级权限打开cmd.exe 2. pip install --upgrade setuptools 3.  pip install -U --ignore-installed wrapt enu ...

  4. R绘制韦恩图 | Venn图

    解决方案有好几种: 网页版,无脑绘图,就是麻烦,没有写代码方便 极简版,gplots::venn 文艺版,venneuler,不好安装rJava,参见Y叔 酷炫版,VennDiagram 特别注意: ...

  5. Gis基础知识,坐标 投影

    1. 大地测量学 (Geodesy) 大地测量学是一门量测和描绘地球表面的学科,也包括确定地球重力场和海底地形. 1.1 大地水准面 (geoid) 大地水准面是海洋表面在排除风力.潮汐等其它影响,只 ...

  6. nginx listen 端口 443 80 https 和 wss

    端口号 443 和 80 端口的区别 一般指定 443 和 80 端口都是使用域名时所需要的 当我们使用域名请求时,一般是不添加端口号的 例如:http://www.baidu.com 在不添加端口号 ...

  7. 阿里druid连接池监控数据自定义存储

    如何将druid连接池监控到的sql执行效率,连接池资源情况等进行持久化存储,方便系统运维分析优化,以下案例初步测试成功. 第一部: 新建MyDruidStatLogger类实现接口 extends ...

  8. 单例模式:Java单例模式的几种写法及它们的优缺点

    总结下Java单例模式的几种写法: 1. 饿汉式 public class Singleton { private static Singleton instance = new Singleton( ...

  9. 一起入门Python1之python的介绍

    之前在某安全论坛发表的一些关于python的文章,但是由于一些问题一直没有完成,那个论坛也歇菜了.放到这儿来吧. 说句默心掏肺的话,我也是才学习python.之所以要这个版主,是为了锻炼自己,也是为了 ...

  10. 001——Typescript 介绍 、Typescript 安 装、Typescript 开发工具

    一. Typescript 介绍 1. TypeScript 是由微软开发的一款开源的编程语言. 4. TypeScript 是 Javascript 的超级,遵循最新的 ES6.Es5 规范.Typ ...