一、基本概念:
1.线程/进程
(1)状态
「Thread.State」:
- NEW:创建了对象,但是没有start
- RUNNABLE:Java线程中,将就绪态「Ready」和运行时「Running」统称为「Runnable」。当某线程被创建后,start被调用后,此线程就进入可运行线程池中,等待调用,获取CPU使用权,此时处于「Ready」,当「Ready」的线程获得了CPU时间片后变为「Running」
- BLOCKED:线程处于阻塞状态
- WAITING:等待,直到其他线程做出特定动作「中断或者通知」
- TIMED_WAITING:超时等待「不同于Waiting,此状态是等待指定时间后自行返回」
- TERMINATED:线程执行完毕
__
「注意」:waiting-不见不散 time-waiting-过时不候
(2)资源
(3)概念
2.并发/并行
(1)执行顺序
(2)安全性
(3)概念
3.案例
(1)「多线程」售票员卖票
「多线程问题」线程操作资源类
「Lambda表达式」 拷贝中括号【里面放置函数体需要的参数】,写死右箭头,落地大括号【当只有一句简单的操作代码时可以省略大括号】
「Lambda表达式」函数接口有且只有一个方法【@FunctionalInterface】
「Lambda表达式」接口可通过default实现方法
「Lambda表达式」定义静态static方法
package com.wtz.juc.saleTicket;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* @author tiezhu
* @Date 2020/7/11 Sat
* Company dtstack
*/
class Ticket {
private int number = 300;
private final Lock lock = new ReentrantLock();
public void sale() {
lock.lock();
try {
if (number > 0) {
System.out.println(Thread.currentThread().getName() + "\t 卖出第 " + (number--) + " 张,还剩 " + number + " 张");
}
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
public class CodeOne {
public static void main(String[] args) {
final Ticket ticket = new Ticket();
new Thread(() -> {
for (int i = 0; i < 400; i++)
ticket.sale();
}, "Thread A").start();
new Thread(() -> {
for (int i = 0; i < 400; i++)
ticket.sale();
}, "Thread B").start();
new Thread(() -> {
for (int i = 0; i < 400; i++)
ticket.sale();
}, "Thread C").start();
/* new Thread(new Runnable() {
public void run() {
for (int i = 0; i < 40; i++) {
ticket.sale();
}
}
}, "Thread A").start();
new Thread(new Runnable() {
public void run() {
for (int i = 0; i < 40; i++) {
ticket.sale();
}
}
}, "Thread B").start();
new Thread(new Runnable() {
public void run() {
for (int i = 0; i < 40; i++) {
ticket.sale();
}
}
}, "Thread C").start();*/
}
}
(2)8锁问题
(3)总结
线程不是按照执行顺序执行的,而是根据争抢资源的结果「先抢到的先执行」
访问同一个资源类,锁的是当前对象,现象是即使对象有多个同步方法,但是一个线程只能访问一个同步方法,因为同步锁锁的是整个资源类对象,而不是某个同步方法
普通方法不与同步方法争抢资源
「静态同步锁」Static 属于整个类,静态同步锁锁整个类,普通的同步锁锁对象
二、JUC
1.Java.util.concurrent
2.Java.util.concurrent.locks
(1)可重入锁【ReentrantLock】
try - finally 开始前先上锁,最后一定要释放锁【可通过设置 idea 快捷键保证自己不会忘记在 finally 释放锁】
3.Java.util.concurrent.atomic
4.Java.util.ConcurrentModificationException
(1)故障现象
抛出 Java.util.ConcurrentModificationException 异常
(2)原因
(3)解决
将ArrayList转化为Vector【并发性下降】
Collections.synchoronizedList(new ArrayList<>())【版本较老】
CopyOnWriteArrayList()【写时复制】读写分离
(4)优化建议
Map -> concurrentHashMap
Set -> CopyOnWriteSet
List -> CopyOnWriteArrayList