Johuer's Blog

多学知识,精简代码

0%

码出高效java开发手册-小结03

1、线程安全

并发、并行概念

并行:指两个或者多个事件在同一时刻发生 (边吃饭边打电话同一时间发生)

并发:指两个或多个事件在同一时间间隔发生(吃饭电话吃饭交替执行)

线程状态:

NEW: 新建状态,线程被创建且未启动的状态

RUNNABLE: 就绪状态,调用start()之后,运行之前的状态

RUNNING: 运行状态,run()正在执行时线程的状态

BLOCKED: 阻塞状态

DEAD: 终止状态,run()结束后的状态,此状态不可逆转

线程安全核心理念就是“要么只读,要么加锁”

java中并发包

  • 线程同步类:CountDownLatch、 Semaphore、 CyclicBarrier 等
  • 并发集合类:ConcurrentHashMap、ConcurrentSkipListMap、 CopyOnWriteArrayList、 BlockingQueue 等
  • 线程管理类:ThreadLocal
  • 锁相关类:Lock、ReentrantLock

2、java中实现锁

  • 用并发包中华锁类
  • 利用同步代码块

3、线程同步

volatile

多线程共享变量的可见性,类似synchronized, 但不具备synchronized的互斥性

信号量同步

1、CountDownLatch: 比如有一个主线程main,它要等待其他3个任务执行完毕之后才能执行;如果其中一个线程出现异常,主线程main一直阻塞

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
public class CountDownLatchTest {
public static void main(String[] args) throws InterruptedException {
CountDownLatch count = new CountDownLatch(3);

new TranslateThread("1st", count).start();
new TranslateThread("2nd", count).start();
new TranslateThread("3rd", count).start();

// 调用await()方法的线程会被挂起,它会等待直到count值为0才继续执行;
// 如果其中一个线程未执行countDown()方法,则线程一直阻塞;
count.await();
System.out.println("所有线程执行完毕");
}
}

class TranslateThread extends Thread {
private String content;
private CountDownLatch count;
public TranslateThread(String content, CountDownLatch count) {
this.content = content;
this.count = count;
}

@Override
public void run() {

if (Math.random() > 0.5) {
throw new RuntimeException("出现异常");
}
System.out.println(content + " 已完成");
count.countDown();
}
}

运行结果

1
2
3
4
Exception in thread "Thread-0" java.lang.RuntimeException: 存在非法字符
at com.concurrency.TranslateThread.run(CountDownLatchTest.java:46)
2nd content的翻译已经完成,译文是...
3rd content的翻译已经完成,译文是...

2、Semaphore: 可以控制同时访问的线程个数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
public class CustomCheckWindow {
public static void main(String[] args) {
Semaphore semaphore = new Semaphore(3);
for (int i = 1; i <= 5; i++) {
new SecurityCheckThread(i, semaphore).start();
}
}

private static class SecurityCheckThread extends Thread {
private int seq;
private Semaphore semaphore;

public SecurityCheckThread(int seq, Semaphore semaphore) {
this.seq = seq;
this.semaphore = semaphore;
}

@Override
public void run() {
try {
semaphore.acquire();
System.out.println("No." + seq + " 乘客,正在检验中");
if (seq % 2 == 0) {
Thread.sleep(1000);
System.out.println("No." + seq + " 乘客,身份可疑,不能出国!");
}

} catch (InterruptedException e) {
e.printStackTrace();
} finally {
semaphore.release();
System.out.println("No." + seq + " 乘客已完成服务");
}
}
}
}

运行结果

1
2
3
4
5
6
7
8
9
10
11
12
No.1 乘客,正在检验中
No.3 乘客,正在检验中
No.2 乘客,正在检验中
No.3 乘客已完成服务。
No.1 乘客已完成服务。
No.4 乘客,正在检验中
No.5 乘客,正在检验中
No.5 乘客已完成服务。
No.2乘客, 身份可疑,不能出国!
No.2 乘客已完成服务。
No.4乘客, 身份可疑,不能出国!
No.4 乘客已完成服务。