Java 与多线程
作者: dkvirus 发表于: 2018-08-13 15:45:48 最近更新: 2018-08-14 22:39:19

本文学习素材为 how2j-java中级-多线程。目前多线程的问题实际接触的并不多,光靠 how2j 上的应用场景没有理解的很充分,记录个 category,等遇到实际多线程问题再回过头一一填充。

一、概述

1. 什么是线程

双击 lol.exe 运行程序,此时就启动了一个进程。一个进程可以同时做很多事,每个事由单独一个线程完成。

一场团战,盖伦击杀提莫,女枪击杀盲僧,如果没有多线程,那就只有等盖伦杀死提莫之后,女枪才开始击杀盲僧。显然,实际情况并不是这样的,盖伦击杀提莫与女枪击杀盲僧可以同时进行,这个动作由两个线程完成。

2. 创建线程的两种方法

dto 类 Hero.java。

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
public class Hero {

// 英雄名字
private String name;

// 英雄当前血量
private float hp;

// 英雄每次受到的伤害值
private float damage;

/**
* 攻击英雄
* @param h
*/
public void attackHero(Hero h) {
try {
Thread.sleep(1000);
} catch (Exception e) {
e.printStackTrace();
}

h.hp -= h.damage;
System.out.format("%s 正在攻击 %s,%s 的生命值变为 %.0f %n", this.name, h.name, h.name, h.hp);

if (h.isDead()) {
System.out.format("%s 杀死了 %s %n", this.name, h.name);
}

}

/**
* 是否死亡
* @return
*/
public boolean isDead() {
return 0 >= this.hp ? true : false;
}

}

2.1 方法一:继承 Thread 类

继承 Thread 类并重写 run() 方法。

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
public class KillThread extends Thread {

private Hero h1;

private Hero h2;

public KillThread(Hero h1, Hero h2) {
this.h1 = h1;
this.h2 = h2;
}

/**
* 线程类的 run 方法
*/
@Override
public void run() {
while (!this.h2.isDead()) {
this.h1.attackHero(this.h2);
}
}

/**
* 主方法,测试调用线程
*
* 创建 KillThread 实例对象,并调用 start(),内部会自动调用 run()
* @param args
*/
public static void main(String[] args) {

Hero gareen = new Hero();
gareen.setName("盖伦");
gareen.setHp(616);
gareen.setDamage(50);

Hero teemo = new Hero();
teemo.setName("提莫");
teemo.setHp(300);
teemo.setDamage(30);

Hero bh = new Hero();
bh.setName("赏金猎人");
bh.setHp(500);
bh.setDamage(65);

Hero leesin = new Hero();
leesin.setName("盲僧");
leesin.setHp(455);
leesin.setDamage(80);

KillThread killThread = new KillThread(gareen, teemo);
killThread.start(); // 会自动调用 run() 方法

KillThread killThread2 = new KillThread(bh, leesin);
killThread2.start();

}

}

2.2 方法二:实现 Runnable 接口

实现 Runnable 接口并实现 run() 方法。

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
public class Battle implements Runnable {

private Hero h1;

private Hero h2;

public Battle (Hero h1, Hero h2) {
this.h1 = h1;
this.h2 = h2;
}

/**
* 实现 Runnable 接口的 run 方法
*/
public void run() {
while (!this.h2.isDead()) {
this.h1.attackHero(this.h2);
}
}

/**
* 主方法,测试调用线程
*
* 创建 Battle 实例对象,并通过 new Thread(battle).start() 执行内部 run()
* @param args
*/
public static void main(String[] args) {

Hero gareen = new Hero();
gareen.setName("盖伦");
gareen.setHp(616);
gareen.setDamage(50);

Hero teemo = new Hero();
teemo.setName("提莫");
teemo.setHp(300);
teemo.setDamage(30);

Hero bh = new Hero();
bh.setName("赏金猎人");
bh.setHp(500);
bh.setDamage(65);

Hero leesin = new Hero();
leesin.setName("盲僧");
leesin.setHp(455);
leesin.setDamage(80);

Battle battle = new Battle(gareen, teemo);
new Thread(battle).start();

Battle battle2 = new Battle(bh, leesin);
new Thread(battle2).start();

}

}

3. 线程常用方法

1)Thread.sleelp()

当前线程睡眠 1000ms 后再继续执行。

1
2
3
4
5
6
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

二、线程中常见的问题

线程中存在很多潜在的问题,了解这些问题是什么,以及如何解决对应的问题很有必要。

1. 线程同步问题

1)什么是多线程同步问题

多线程的同步问题指的是多个线程同时修改一个数据的时候,可能导致的问题。concurrency 中文意思,并发性。

2)如何解决多线程同步问题

synchronized 关键字。

lock 关键字。

2. 线程安全类

记得刚培训完 java 面试的时候最常被问到的一个问题就是 StringBuffer 和 StringBuilder 的区别?当时回答前者是线程安全类,后者是非线程安全的类。说实话,至于什么是线程安不安全,一直不明白什么个意思。

3. 线程死锁问题

  • 线程1 首先占有对象1,接着试图占有对象2
  • 线程2 首先占有对象2,接着试图占有对象1
  • 线程1 等待线程2释放对象2
  • 与此同时,线程2等待线程1释放对象1
  • 等啊等,就变成了死锁

4. 线程交互问题

不同线程之间存在交互的问题。具体怎么交互??

how2j 举的线程之间交互通知的需求实际应用场景:

  • 有两个线程,处理同一个英雄。
  • 一个加血,一个减血。
  • 减血的线程,发现血量=1,就停止减血,直到加血的线程为英雄加了血,才可以继续减血

5. 线程池

1)线程池解决的问题

每一个线程的启动和结束都是比较消耗时间和占用资源的。如果在系统中用到了很多的线程,大量的启动和结束动作会导致系统的性能变卡,响应变慢。为了解决这个问题,引入线程池这种设计思想。

2)怎么实现线程池功能

TODO

首页
友链
归档
dkvirus
动态
RSS