>多线程创建方式

继承一个类 Thread

或者实现一个接口 Runnable

重写其中的 run() 方法(对于实现接口的形式,并没有继承run() 方法,要通过构造扔到一个Thread对象中去运行)

使用 start() 方法

>原子性操作

多线程环境下,如果一个操作不是原子性操作,那么需要考虑它的安全性。

什么是原子性操作?

不可分割的操作

++i;是不是原子性操作?

不是,在 jvm 中分为三步:取出 i 的值;让 i 的值加一; 将自加后的值赋给 i 。

>举个例子,四个线程,每个线程加一万次

public class ReTh {int i = 0;//加锁,因为 i 是非原子性操作,可能第一线程自加未赋值,后续线程又进行了操作public synchronized void add() {++i;}public static void main(String[] args) {ReTh rt = new ReTh();for (int i = 0; i < 4; i++) {new Thread(new Runnable() {@Overridepublic void run() {for (int i = 0; i < 10000; i++) {rt.add();}}}).start();}while (Thread.activeCount() > 1) {//等待,并发就是多个分支一并往下走,如果这里不等待,主线程就在四个线程没加完//的时刻就进行了打印 i,得不到40000}System.out.println(rt.i);//40000}}

>线程控制

首先要明确,并发的线程,抢占式运行。

三种线程控制:

join()  加塞:

一个线程过来,有"急事",让他独立占用cpu,等它执行完了,我再执行,我们并不是并行关系。

sleep()  睡眠 :

让当前线程睡眠多久。当前线程醒来的时候,是重新竞争CPU,还是?

当这个线程"睡觉"的时候,是抱着cpu"睡觉",醒来的时候直接获得执行权力。

yield()  让步/放弃:

当一个线程获得cpu执行权力,调用yield,放弃执行权力,退一步,大家再重新抢。

>线程的生命周期

新建:当我们创建了线程对象的时候。

就绪:当我们调用了线程的 start 方法之后。

运行:当获取了cpu的时候

阻塞:单说。

死亡:运行完。或者运行的时候抛出异常。

>阻塞

线程进入阻塞状态的情况:

  • 线程调用了一个阻塞方法,方法返回之前该线程一直阻塞。
  • 线程调用 sleep() 方法进入阻塞。
  • 线程尝试获取 同步监视器 ,但该同步监视器被其他线程持有。
  • 线程调用 suspend() 方法挂起。

>线程优先级(不可靠,不要依赖优先级控制线程)

new Thread().setPriority(Thread.MAX_PRIORITY);

>线程安全(重点)

多个线程操作的同一个类的同一个对象时,会存在线程安全问题。

解决:同步代码块/同步方法

public class TestSafe {V v = new V();public void go() {new Thread(new Runnable() {@Overridepublic void run() {// TODO Auto-generated method stubwhile (true) {try {Thread.sleep(10);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}v.printString("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA");}}}).start();new Thread(new Runnable() {@Overridepublic void run() {// TODO Auto-generated method stubwhile (true) {try {Thread.sleep(10);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}v.printString("BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB");}}}).start();}class V {public synchronized void printString(String s) {/*** 假设这里有大量业务代码,如何降低 锁 的粒度?*/synchronized (String.class) {}for (int i = 0; i < s.length(); i++) {System.out.print(s.charAt(i));}System.out.println();/*** 假设这里有大量业务代码*/}}public static void main(String[] args) {TestSafe t = new TestSafe();t.go();}}

>wait / notify,notifyAll(重点)

1.首先明确一点,这三个方法不是Thread类的方法,是Object类的native方法。

2.要调用这些方法,必须获得同步监视器(锁),否则会报异常(换句话说我们线程在调用这些方法的地方,要有synchronized关键字,这样执行,就会获取锁)。

补充:

1)静态方法上的锁

静态方法是属于“类”,不属于某个实例,是所有对象实例所共享的方法。也就是说如果在静态方法上加入synchronized,那么它获取的就是这个类的锁,锁住的就是这个类。

2)实例方法(普通方法)上的锁,锁住的就是这个对象实例,synchronized(this){}也是锁的对象。

3.wait 的意思:等待时机成熟再执行,否则就等待。

再执行的时候,必须被别的线程唤醒,它自己醒不了。

4.notify/notifyAll ,专门唤醒等待队列中的线程(随机唤醒某一个/唤醒所有的),唤醒之后再判断条件是否满足。

>轮询执行的问题

这种问题的思路:同一时刻只能让一个线程在运行,其他线程wait() 等待唤醒,如果同一时刻多个线程抢占CPU就失去了控制;线程的运行和唤醒要通过额外的 条件/flag 进行轮询的控制。

写一个程序,让两个线程轮询执行 ?

public class TestWaitNotify {public static void main(String[] args) {TestWaitNotify t = new TestWaitNotify();t.go();}V v = new V();private void go() {new Thread(new Runnable() {@Overridepublic void run() {while (true) {v.f1();}}}, "A线程").start();new Thread(new Runnable() {@Overridepublic void run() {while (true) {v.f2();}}}, "B线程").start();}class V {public boolean flag=true;public synchronized void f1() {while(flag){try {wait();} catch (InterruptedException e) {e.printStackTrace();}}System.out.println("F1 " + Thread.currentThread().getName());flag=true;notifyAll();}public synchronized void f2() {while(!flag){try {wait();} catch (InterruptedException e) {e.printStackTrace();}}System.out.println("F2 " + Thread.currentThread().getName());flag=false;notifyAll();}}
}

三个线程轮询执行?

public class ThreeThreadInTurn {public static void main(String[] args) {ThreeThreadInTurn t = new ThreeThreadInTurn();t.go();}V v = new V();public void go() {new Thread(new Runnable() {@Overridepublic void run() {while (true) {v.f1();}}}, "线程1").start();new Thread(new Runnable() {@Overridepublic void run() {while (true) {v.f2();}}}, "线程2").start();new Thread(new Runnable() {@Overridepublic void run() {while (true) {v.f3();}}}, "线程3").start();}class V {int flag = 1;public synchronized void f1() {while (flag != 1) {try {wait();} catch (InterruptedException e) {e.printStackTrace();}}System.out.println("F1 " + Thread.currentThread().getName());flag = 2;notifyAll();}public synchronized void f2() {while (flag != 2) {try {wait();} catch (InterruptedException e) {e.printStackTrace();}}System.out.println("F1 " + Thread.currentThread().getName());flag = 3;notifyAll();}public synchronized void f3() {while (flag != 3) {try {wait();} catch (InterruptedException e) {e.printStackTrace();}}System.out.println("F1 " + Thread.currentThread().getName());flag = 1;notifyAll();}}}

Java 并发(入门梳理)相关推荐

  1. Java并发知识梳理(上):并发优缺点,线程状态转换,Java内存模型,Synchronized,Volatile,final,并发三特性,Lock与AQS,ReetrandLock

    努力的意义,就是,在以后的日子里,放眼望去全是自己喜欢的人和事! 整个系列文章为Java并发专题,一是自己的兴趣,二是,这部分在实际理解上很有难度,另外在面试过程中也是经常被问到.所以在学习过程中,记 ...

  2. 《Java并发编程入门与高并发面试》or 《Java并发编程与高并发解决方案》笔记

    <Java并发编程入门与高并发面试>or <Java并发编程与高并发解决方案>笔记 参考文章: (1)<Java并发编程入门与高并发面试>or <Java并发 ...

  3. Java高并发入门-线程初步(二)

    Java高并发入门详细讲解 上期回顾及问题总结 上次说了创建线程的两种常用方式,第三种方式在后面的更新中会讲解到.这里对于上一节的内容做个回顾. 在上一节中说到了创建多线程的问题,分析了Thread的 ...

  4. Java高并发入门-线程初步

    Java高并发入门-线程初步 线程与进程之间的关系 进程就是我们运行在计算机上的一个程序,对应Java程序来说就是运行在计算机上的Java应用程序,这个程序在运行的时候就会创建了一个进程,服务器上就会 ...

  5. 学习笔记:Java 并发编程①_基础知识入门

    若文章内容或图片失效,请留言反馈. 部分素材来自网络,若不小心影响到您的利益,请联系博主删除. 视频链接:https://www.bilibili.com/video/av81461839 视频下载: ...

  6. Java并发编程(中下篇)从入门到深入 超详细笔记

    接上一篇博客笔记:Java并发编程(中上篇)从入门到深入 超详细笔记_未来很长,别只看眼前的博客-CSDN博客https://blog.csdn.net/weixin_53142722/article ...

  7. java并发编程入门_探讨一下!Java并发编程基础篇一

    Java并发编程想必大家都不陌生,它是实现高并发/高流量的基础,今天我们就来一起学习这方面的内容. 什么是线程?什么是进程?他们之间有什么联系? 简单来说,进程就是程序的一次执行过程,它是系统进行资源 ...

  8. 2021全新Java多线程并发入门到精通,一篇就能学会

    目录 一, JAVA 多线程并发 1,JAVA 并发知识库 2,JAVA 线程实现/创建方式 (1) 继承 Thread 类 (2)实现 Runnable 接口. (3)ExecutorService ...

  9. Java并发技术要点梳理

    写在前面: Java并发这块内容无论是在工作中还是面试中都是常见而且实用的重点,推荐将本文一些关键代码自己运行一遍,以查看实际效果,这里推荐一个在线运行Java代码的网站 基本概念 名词解释 CPU线 ...

  10. Java 并发编程入门

    JUC 写在前面 推荐阅读 http://ifeve.com/java-memory-model-1/ :深入理解 Java 内存模型-程晓明 https://segmentfault.com/a/1 ...

最新文章

  1. 职场中怎样评估系统架构师的成绩?
  2. Android开发之LisitView的图文并排效果实现(源代码分享)
  3. appserv 安装后phpmyadmin 密码问题 win7
  4. (一)SpringBoot 整合 MyBatis
  5. CockroachDB学习笔记——[译]在CockroachDB中如何让在线模式更改成为可能
  6. 啊哈算法-游戏币问题(dp)
  7. Intel开发工具之VTune
  8. 【Oracle】lsnrctl reload 命令简介
  9. 在网页中加入神奇的效果
  10. G-Sensor 校准标准
  11. android view强制重绘_安卓自定义 view 不能正常重绘
  12. c++ 栈 STL的基本操作
  13. 播布客全部视频教程汇总
  14. js高级--jsonp跨域
  15. 解决winform中的panel重绘闪烁问题
  16. Android studio:select process to attach to...找不到debug调试的目录
  17. 伦敦金走势图与顾比均线
  18. win10OneNote登录微软 账号登陆出现错误码0x80190001
  19. git runner 配置_GitLab Runner 入门及常见问题
  20. 陪伴我成长的学习工作邮箱品牌——TOM邮箱

热门文章

  1. 突变检测软件 测试数据库,测序数据比对和变异检测
  2. mongodb运算符使用
  3. Hyper-v副本容量规划器
  4. 社交系统ThinkSNS可以运营什么?可以应用于什么场景?
  5. EasyUI——DataGrid中嵌入Radio
  6. 用javascript写Android和iOS naitve应用,实在炫酷。
  7. 安装Windows Service总是发生异常!
  8. 将byte数组写进文件,指定buffer size
  9. 启动器和选择器学习-----(1)总括
  10. Java中的weak reference 和 soft reference