回顾多线程
线程的六个状态
//获取CPU的核数
System.out.println(
Runtime.getRuntime()
.availableProcessors()
);
//Thread 的六种状态,枚举
Thread.State.values()
public enum State {
NEW,
RUNNABLE,
BLOCKED,
WAITING,
TIMED_WAITING,
TERMINATED;
}
操作系统层面是 5个, java 定义了 6个
wait 和 sleep区别
1.锁的释放
- wait释放锁,sleep抱着锁睡觉,不释放
2.使用范围不同
- wait必须在同步代码块中
- sleep可以在任意一个地方睡
- 是否需要捕获异常(wait不用捕获异常,sleep必须捕获异常)
3. lock
3. Synchronized 和 lock的区别
- synchronized 是内置的java关键字, Lock是一个java类
- Synchronized 无法判断获取锁的状态,Lock 可以判断是否获取到了锁
- Synchronized 全自动释放锁
- lock必须手动释放锁,不然就是死锁
- lock锁有一个 tryLock的方法,可以尝试获取锁(可以判断锁的状态),不一定像Synchronized锁一样,一直阻塞下去
- Synchronized 可重入锁,不可以中断,非公平; lock,可重入,不可以中断,非公平(也可以改成公平锁),相比之下,lock比较灵活
线程中的协作问题!!(生产者和消费者的协作)
package example;
/**
* @Author lyr
* @create 2020/5/29 19:01
*/
public class Main {
public static void main(String[] args) throws ClassNotFoundException {
Resource s = new Resource();
new Thread(()->{
for(int i=0;i<10;++i) {
s.incr();
}
},"A线程").start();
new Thread(()->{
for(int j=0;j<10;++j) {
s.decr();
}
},"B线程").start();
}
static class Resource {
private int number;
// private Object monitor;
public synchronized void incr() {
while (number>0) {
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
this.number++;
System.out.println("A线程 "+number);
this.notifyAll();
}
public synchronized void decr() {
while (number<=0) {
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
this.number--;
System.out.println("B线程 "+number);
this.notifyAll();
}
}
}
4.线程的协作
使用Condition 的优势!
Condition 可以代替 signal 随机分布,也可以是的线程有序执行,即 你可以使用 condition 精准的通知线程
有序执行。
package example;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* @Author lyr
* @create 2020/5/29 19:01
*/
public class Main {
public static void main(String[] args) throws ClassNotFoundException {
Resource s = new Resource();
new Thread(()->{
for(int i=0;i<10;++i) {
s.printA();
}
},"A线程").start();
new Thread(()->{
for(int j=0;j<10;++j) {
s.printB();
}
},"B线程").start();
new Thread(()->{
for(int j=0;j<10;++j) {
s.printC();
}
},"C线程").start();
}
static class Resource {
private int number = 1;
private Lock lock = new ReentrantLock();
private Condition conditionA = lock.newCondition();
private Condition conditionB = lock.newCondition();
private Condition conditionC = lock.newCondition();
public void printA() {
lock.lock();
try{
while (number!=1) {
conditionA.await();
}
System.out.println(
Thread.currentThread().getName()
);
number = 2;
conditionB.signal();
}catch (Exception ex) {
System.out.println(ex);
}finally {
lock.unlock();
}
}
public void printB() {
lock.lock();
try{
while (number!=2) {
conditionB.await();
}
System.out.println(
Thread.currentThread().getName()
);
number = 3;
conditionC.signal();
}catch (Exception ex) {
System.out.println(ex);
}finally {
lock.unlock();
}
}
public void printC() {
lock.lock();
try{
while (number!=3) {
conditionC.await();
}
System.out.println(
Thread.currentThread().getName()
);
number = 1;
conditionA.signal();
}catch (Exception ex) {
System.out.println(ex);
}finally {
lock.unlock();
}
}
}
}
copyOnWriteArrayList
copyOnwrite 采用写入时复制,读写分离的方式。
只在写操作的时候加锁。
public boolean add(E e) {
final ReentrantLock lock = this.lock;
lock.lock();
try {
Object[] elements = getArray();
int len = elements.length;
Object[] newElements = Arrays.copyOf(elements, len + 1);
newElements[len] = e;
setArray(newElements);
return true;
} finally {
lock.unlock();
}
}
final void setArray(Object[] a) {
array = a;
}
我们先试试在多线程中打印 操作 ArrayList
并发修改异常
package example;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
/**
* @Author lyr
* @create 2020/5/29 19:01
*/
public class Main {
public static void main(String[] args) throws ClassNotFoundException {
List list = new ArrayList<>();
for(int i=1;i<10;++i) {
new Thread(()->{
list.add(UUID.randomUUID().toString());
System.out.println(list);
}).start();
}
}
}
null, d43b5115-f131-4a9a-8c17-685d1463c298, e3a0ddf5-1906-4b86-9367-6b2c46313139, 42143054-8fb2-4810-a6b2-73ee99325b04, f9579c0e-144b-4b28-8ee4-b0d92fb1c63d, 48d97a2c-59e1-4b96-823e-ed41aae01703, 9bfdddc9-e3df-4757-bfc0-cc62408f57d5]
[null, d43b5115-f131-4a9a-8c17-685d1463c298, e3a0ddf5-1906-4b86-9367-6b2c46313139, 42143054-8fb2-4810-a6b2-73ee99325b04, f9579c0e-144b-4b28-8ee4-b0d92fb1c63d, 48d97a2c-59e1-4b96-823e-ed41aae01703]
Exception in thread “Thread-4” Exception in thread “Thread-0” Exception in thread “Thread-3” Exception in thread “Thread-6” java.util.ConcurrentModificationException
at java.util.ArrayList I t r . c h e c k F o r C o m o d i f i c a t i o n ( A r r a y L i s t . j a v a : 909 ) a t j a v a . u t i l . A r r a y L i s t Itr.checkForComodification(ArrayList.java:909) at java.util.ArrayList Itr.checkForComodification(ArrayList.java:909)atjava.util.ArrayListItr.next(ArrayList.java:859)
at java.util.AbstractCollection.toString(AbstractCollection.java:461)
at java.lang.String.valueOf(String.java:2994)
at java.io.PrintStream.println(PrintStream.java:821)
at example.Main.lambda$main 0 ( M a i n . j a v a : 19 ) a t j a v a . l a n g . T h r e a d . r u n ( T h r e a d . j a v a : 748 ) j a v a . u t i l . C o n c u r r e n t M o d i f i c a t i o n E x c e p t i o n a t j a v a . u t i l . A r r a y L i s t 0(Main.java:19) at java.lang.Thread.run(Thread.java:748) java.util.ConcurrentModificationException at java.util.ArrayList 0(Main.java:19)atjava.lang.Thread.run(Thread.java:748)java.util.ConcurrentModificationExceptionatjava.util.ArrayListItr.checkForComodification(ArrayList.java:909)
at java.util.ArrayList I t r . n e x t ( A r r a y L i s t . j a v a : 859 ) a t j a v a . u t i l . A b s t r a c t C o l l e c t i o n . t o S t r i n g ( A b s t r a c t C o l l e c t i o n . j a v a : 461 ) a t j a v a . l a n g . S t r i n g . v a l u e O f ( S t r i n g . j a v a : 2994 ) a t j a v a . i o . P r i n t S t r e a m . p r i n t l n ( P r i n t S t r e a m . j a v a : 821 ) a t e x a m p l e . M a i n . l a m b d a Itr.next(ArrayList.java:859) at java.util.AbstractCollection.toString(AbstractCollection.java:461) at java.lang.String.valueOf(String.java:2994) at java.io.PrintStream.println(PrintStream.java:821) at example.Main.lambda Itr.next(ArrayList.java:859)atjava.util.AbstractCollection.toString(AbstractCollection.java:461)atjava.lang.String.valueOf(String.java:2994)atjava.io.PrintStream.println(PrintStream.java:821)atexample.Main.lambdamain 0 ( M a i n . j a v a : 19 ) a t j a v a . l a n g . T h r e a d . r u n ( T h r e a d . j a v a : 748 ) j a v a . u t i l . C o n c u r r e n t M o d i f i c a t i o n E x c e p t i o n a t j a v a . u t i l . A r r a y L i s t 0(Main.java:19) at java.lang.Thread.run(Thread.java:748) java.util.ConcurrentModificationException at java.util.ArrayList 0(Main.java:19)atjava.lang.Thread.run(Thread.java:748)java.util.ConcurrentModificationExceptionatjava.util.ArrayListItr.checkForComodification(ArrayList.java:909)
at java.util.ArrayList I t r . n e x t ( A r r a y L i s t . j a v a : 859 ) a t j a v a . u t i l . A b s t r a c t C o l l e c t i o n . t o S t r i n g ( A b s t r a c t C o l l e c t i o n . j a v a : 461 ) a t j a v a . l a n g . S t r i n g . v a l u e O f ( S t r i n g . j a v a : 2994 ) a t j a v a . i o . P r i n t S t r e a m . p r i n t l n ( P r i n t S t r e a m . j a v a : 821 ) a t e x a m p l e . M a i n . l a m b d a Itr.next(ArrayList.java:859) at java.util.AbstractCollection.toString(AbstractCollection.java:461) at java.lang.String.valueOf(String.java:2994) at java.io.PrintStream.println(PrintStream.java:821) at example.Main.lambda Itr.next(ArrayList.java:859)atjava.util.AbstractCollection.toString(AbstractCollection.java:461)atjava.lang.String.valueOf(String.java:2994)atjava.io.PrintStream.println(PrintStream.java:821)atexample.Main.lambdamain 0 ( M a i n . j a v a : 19 ) a t j a v a . l a n g . T h r e a d . r u n ( T h r e a d . j a v a : 748 ) j a v a . u t i l . C o n c u r r e n t M o d i f i c a t i o n E x c e p t i o n a t j a v a . u t i l . A r r a y L i s t 0(Main.java:19) at java.lang.Thread.run(Thread.java:748) java.util.ConcurrentModificationException at java.util.ArrayList 0(Main.java:19)atjava.lang.Thread.run(Thread.java:748)java.util.ConcurrentModificationExceptionatjava.util.ArrayListItr.checkForComodification(ArrayList.java:909)
at java.util.ArrayList I t r . n e x t ( A r r a y L i s t . j a v a : 859 ) a t j a v a . u t i l . A b s t r a c t C o l l e c t i o n . t o S t r i n g ( A b s t r a c t C o l l e c t i o n . j a v a : 461 ) a t j a v a . l a n g . S t r i n g . v a l u e O f ( S t r i n g . j a v a : 2994 ) a t j a v a . i o . P r i n t S t r e a m . p r i n t l n ( P r i n t S t r e a m . j a v a : 821 ) a t e x a m p l e . M a i n . l a m b d a Itr.next(ArrayList.java:859) at java.util.AbstractCollection.toString(AbstractCollection.java:461) at java.lang.String.valueOf(String.java:2994) at java.io.PrintStream.println(PrintStream.java:821) at example.Main.lambda Itr.next(ArrayList.java:859)atjava.util.AbstractCollection.toString(AbstractCollection.java:461)atjava.lang.String.valueOf(String.java:2994)atjava.io.PrintStream.println(PrintStream.java:821)atexample.Main.lambdamain$0(Main.java:19)
at java.lang.Thread.run(Thread.java:748)
如何让集合操作安全?
- vector
- List list = Collections.synchronizedList(new ArrayList<>());
- CopyOnWriteArrayList 或者其他的一些工具类