Lab Final: 多线程(Threading)

考虑到理论课进度,本次 Lab 时长为 4 周,你可以选择现阶段自学完成或等老师讲授相关内容后再完成,DDL 为 12 月 18 日 23:59

附件下载(包括问答题和实验报告模板,以及往年的 PPT 参考):https://bhpan.buaa.edu.cn/link/AA96D0CA694BB74ABFA070F38B6C527AC6

实验目的

  • 理解程序、进程和多线程概念及特点

  • 理解线程的状态、生命周期及调度策略

  • 理解并掌握线程类 ThreadRunnable 接口,并能够进行相关应用的程序设计,实现多线程编程

实验题目

Question 1: 简述程序,进程,线程的概念(简答)

Question 2: 产生死锁的四个条件是什么?(简答)

Question 3: 创建线程的两种方式分别是什么?各有什么优缺点(简答)

Question 4: 判断题

(1) 进程是线程 Thread 内部的一个执行单元,它是程序中一个单一顺序控制流程。

(2) 一个进程可以包括多个线程。两者的一个主要区别是:线程是资源分配的单位,而进程是 CPU 调度和执行的单位。

(3) 线程可以用 yield 使低优先级的线程运行。

(4) 当一个线程进入一个对象的一个 synchronized 方法后,其它线程可以再进入该对象的其它同步方法执行。

(5) notify 是唤醒所在对象 wait pool 中的第一个线程。

Question 5: 程序输出

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
public class Main {
public static void main(String[] args) {
SyncThread syncThread = new SyncThread();
Thread thread1 = new Thread(syncThread, "SyncThread1");
Thread thread2 = new Thread(syncThread, "SyncThread2");
thread1.start();
thread2.start();
}
}

class SyncThread implements Runnable {
private static int count;
public SyncThread() {
count = 0;
}

public synchronized void run() {
for (int i = 0; i < 5; i++) {
try {
System.out.println(Thread.currentThread().getName() + ": " + (count++));
Thread.sleep(100); //【1】
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

public int getCount() {
return count;
}
}

(1) 写出上述程序的输出

(2) 用 synchronized 修饰 run () 的作用是什么?

(3) 标号【1】处 sleep 的作用是什么?如果改为 wait (100); 输出会发生改变吗,为什么?

Question 6: 程序补全

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
public class ThreadPrint {
public static void main(String[] args) throws InterruptedException {
Object a = new Object();
Object b = new Object();
Object c = new Object();
Thread8 threadA = new Thread8("A", c, a);
Thread8 threadB = new Thread8("B", a, b);
Thread8 threadC = new Thread8("C", b, c);
new Thread(threadA).start();
Thread.sleep(100);
new Thread(threadB).start();
Thread.sleep(100);
new Thread(threadC).start();
Thread.sleep(100);
}
}

class Thread8 implements Runnable {
private String name;
private Object prev;
private Object self;

public Thread8(String name, Object prev, Object self) {
this.name = name;
this.prev = prev;
this.self = self;
}

@Override
public void run() {
int count = 10;
while (count > 0) {
synchronized (prev) {
synchronized (self) {
System.out.print(name);
count--;
/*【1】*/
}
try {
if (count == 0) {
/*【2】*/
} else {
/*【3】*/
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}

(1) 补全标号处的代码

(2) 详细说明上述程序的功能

(3) 主函数 main 中的 Thread.sleep (100) 语句不能省略,请简述原因。

(4) 主函数 main 中的 Thread.sleep (100) 语句全部去掉后程序可能出现死锁吗?试举例说明。

Question 7: 创建两个线程,其中一个输出 1 - 52,另外一个输出 A - Z。(编程题)

输出示例如下,连续输出两个数字,紧接着输出一个字母,除 Z 外,字母后均有一个空格。

1
12A 34B 56C 78D 910E 1112F 1314G 1516H 1718I 1920J 2122K 2324L 2526M 2728N 2930O 3132P 3334Q 3536R 3738S 3940T 4142U 4344V 4546W 4748X 4950Y 5152Z

注意:

(1) 可以参考上一题。

(2) 12A 34B…… 字母与数字之间是有一个空格的,且输出以 Z 结尾,即结尾不能有空格。

(3) 确保你的程序能够正常结束,不要在输出 Z 之后一直阻塞下去。


恭喜你完成了所有 Lab!🥳

- EOF -