java回顾之多线程

一、多线程

1、并行与并发

并行:多个事件都在执行,并在某个时刻多个事件是同时执行

并发:多个事件都在执行,但是在某个时刻多个事件没有同时执行。

2、进程与线程

进程:一个进程就是应用程序的一次执行

线程:线程是进程的执行单元。一个进程中可以包含多个线程,一个进程起码有一个线程。

3、Thread类

构造方法:

Thread() 创建线程对象   Thread(String name) 创建线程对象并指定线程名字

Thread(Runnable target)  使用Runnable创建线程

Thread(Runnable  target,String name)  使用Runable创建线程并指定线程名字

常用方法:

getName()  获取线程的名字

start()   开启线程,每个对象只调用一次start

run()   run方法写线程执行的代码

sleep() 让当前线程睡指定的时间

currentThread()    获取当前线程对象

4、创建线程的方法

4.1、继承方式

写一个类,继承Thread类,重写run方法,用start开启线程

4.2、实现方式

创建一个类,实现Runnable接口,重写run方法,run方法写线程执行的代码,然后创建对象,将实现接口的对象作为参数,传入Thread对象中

java 多线程 update JAVA 多线程 并行 水印_主线程

这种方式太麻烦,还可以用匿名内部类的方式,直接将代码写出来

一个是匿名内部类继承Thread类,一个是匿名内部类实现Runable接口

java 多线程 update JAVA 多线程 并行 水印_主线程_02

java 多线程 update JAVA 多线程 并行 水印_原子类_03

在普通情况下你想用哪种就用哪种。

java中类是单继承的,如果一个类已经有一个父类了,那么只能实现一个接口而不能再去继承一个类。

匿名内部类的方式完全是为了简化代码,你想用就用不想用就不用。、

4.3 callable开启多线程

callable有两个好处,可以写返回值类型,可以抛出异常。

java 多线程 update JAVA 多线程 并行 水印_主线程_04

5.安全性问题

线程在高并发的情况下,有安全性问题

1、可见性:一个线程将某个变量的值修改了,但是主线程跑的快,当主线程读取到这个变量的值时,值还没有修改,主线程就会默认这个变量的值不会变量,所以当子线程将值修改后,主线程也没有读取到改变的值

java 多线程 update JAVA 多线程 并行 水印_创建线程_05

解决这个问题可以使用volatile关键字修饰成员变量,可以解决可见性问题

public static volatile int a = 0;

5.2有序性问题

代码编译期间,代码没有上下的逻辑关系,系统可能出现代码重排的现象,就是会先执行后面的代码再执行前面的代码

java 多线程 update JAVA 多线程 并行 水印_主线程_06

这个解决办法也是用volitile关键字

5.3原子性问题

当多个线程修改同一个变量的时候,比如线程一对变量a进行自增,当a=1000的时候,线程一正在修改还没有返回,线程二将a=1000读取走了,这时候线程一将a=1001返回,然后线程二也将a=1001返回,a等于了两回1001

java 多线程 update JAVA 多线程 并行 水印_主线程_07

解决原子性问题,第一个方法可以使用原子类来解决

AtomicInteger:对int变量操作的原子类

AtomicLong:对long变量操作的原子类

java 多线程 update JAVA 多线程 并行 水印_java 线程 spring_08

AtomicBoolean:对boolean变量操作的“原子类”;、

AtomicInteger工作机制-CAS机制

java 多线程 update JAVA 多线程 并行 水印_原子类_09

AtomicIntegerArray:原子类数组,解决数组的原子性问题

java 多线程 update JAVA 多线程 并行 水印_创建线程_10

多线程的内存机制

java 多线程 update JAVA 多线程 并行 水印_java 多线程 update_11