多线程的实现方式

通过实现 Runnable 接口

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
package com.ruanyuan;

/**
* TODO
*
* @ClassName TestThread
* @Author Alfa
* @Data 2022/7/14 15:43
* @Version 1.0
**/
public class TestThread{
public static void main(String[] args) {
RunnableDemo demo = new RunnableDemo();
new Thread(demo).start();
for (int i = 0; i < 1000; i++) {
System.out.println("主线程");
}
}
}
class RunnableDemo implements Runnable {
public void run() {
for (int i = 0; i < 1000; i++) {
System.out.println("子线程--"+Thread.currentThread().getName());
}
}
}

推荐使用Runnable对象,因为Java单继承的局限性

通过继承 Thread 类本身

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
package com.ruanyuan;

/**
* TODO
*
* @ClassName TestThread
* @Author Alfa
* @Data 2022/7/14 15:43
* @Version 1.0
**/
public class TestThread{
public static void main(String[] args) {
ThreadRDemo demo = new ThreadRDemo();
demo.start();
for (int i = 0; i < 1000; i++) {
System.out.println("主线程");
}
}
}
class ThreadRDemo extends Thread {
public void run() {
for (int i = 0; i < 1000; i++) {
System.out.println("子线程--"+Thread.currentThread().getName());
}
}
}

线程同步

线程安全案例一

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
package com.ruanyuan;

import java.util.ArrayList;
import java.util.List;

/**
* TODO
*
* @ClassName TestThread
* @Author Alfa
* @Data 2022/7/14 15:43
* @Version 1.0
**/
public class TestThread{
public static void main(String[] args) {
//ArrayList线程不安全案例
List<String> list = new ArrayList<>();
//开启一万个线程操作list
for (int i = 0; i < 10000; i++) {
new Thread(() -> {
list.add(Thread.currentThread().getName());
}).start();
}
// 主线程睡眠三秒,等待一万个子线程执行完毕
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(list.size());
}
}

image-20220714163801117

并发太快,对集合的操作有的重复在了一个位置。

同步代码块

image-20220714171307635

线程安全案例二

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
37
38
39
40
41
42
43
44
45
46
47
package com.ruanyuan;

//不安全买票
public class TestThread {
public static void main(String[] args) {
BuyTicket buyTicket = new BuyTicket();
new Thread(buyTicket, "张三").start();
new Thread(buyTicket, "李四").start();
new Thread(buyTicket, "王五").start();
}
}

class BuyTicket implements Runnable {
//票
private int ticketNums = 10;
boolean flag = true;

@Override
public void run() {
//买票
while (flag) {
try {
buy();
} catch (Exception e) {
e.printStackTrace();
}
}
}

//买票
private void buy() {
//判断是否有票
if (ticketNums <= 0) {
flag = false;
return;
}
//延迟
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}

//买票
System.out.println(Thread.currentThread().getName() + "拿到" + ticketNums--);
}
}

image-20220714172648484

同步方法

image-20220714173011580

死锁

案例

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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
package com.ruanyuan;

/**
* 死锁:多个线程互相抱着对方需要的资源,然后形成僵持
* 解决:一个锁只锁一个对象
*/
public class DeadLock {
public static void main(String[] args) {
MakeUp g1 = new MakeUp(0, "灰姑娘");
MakeUp g2 = new MakeUp(1,"白雪公主");

g1.start();
g2.start();
}
}

//口红
class LipStick{

}

//镜子
class Mirror{

}

class MakeUp extends Thread{
//需要的资源只有一份,用static保证只有一份
static LipStick lipStick = new LipStick();
static Mirror mirror = new Mirror();

//选择
int choice;
//使用化妆品的人
String girlName;

public MakeUp(int choice, String girlName) {
this.choice = choice;
this.girlName = girlName;
}

@Override
public void run() {
//化妆
makeup();
}

//化妆,互相持有对方的锁
private void makeup(){
if (choice == 0)
{
synchronized (lipStick) {
// 获得口红的锁
System.out.println(this.girlName+"获得口红的锁");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (mirror) {
//一秒钟后想要获得镜子
System.out.println(this.girlName+"获得镜子的锁");
}
}
} else {
synchronized (mirror) {
// 获得镜子的锁
System.out.println(this.girlName+"获得镜子的锁");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (lipStick) {
//两秒钟后想要获得镜子
System.out.println(this.girlName+"获得口红的锁");
}
}
}
}
}

解决

image-20220715092321508

image-20220715092603663