感兴趣的小伙伴可以先看看我的这篇文章哦,打开看看,说不定能帮到你一些~~
写在前面:
本文的题目均为自己编造的,老师并没有给出这次实验报告的选题,要求我们自由发挥,自己创造背景,要包含进线程设计,线程互斥与同步的知识点,于是我就自己编了两个题目,没有仔细看,可能存在一些问题,如有各位大佬发现问题,还请帮忙指正!其中第一道题体现了线程互斥,第二道题体现了线程同步,这两题又都体现了如何进行线程设计。本文给出了我编的题目,实现代码以及运行结果,对于本次的实验报告,本文仅供参考,具体还得依据各位自己所创造的背景来完成。
好了,不说废话了,上题目。
1.小王,小李,小陈三人都要使用办公室的打印机进行打印,三个人都要打印十份材料。而办公室只有一台打印机可供打印,简言之,此三人共有三个打印线程,三个打印线程争夺一台打印机资源,形成了线程互斥,为了让此三人各自的打印任务都能完成且不出现问题,使用相关方法编写一个程序处理该线程互斥问题。其中需要定义打印机Printer类,其中有用于统计打印材料总数的count,用于打印的方法print,需要定义继承Thread类的材料打印类MaterialPrint,重写run()方法,其中调用print方法。在测试类中创建三个人的材料打印线程并启动。最终要求实现线程互斥的解决。
这里说明一下有关线程互斥:
当多个线程需要访问同一资源时,要求在一个时间段内只能允许一个线程来操作共享资源,操作完毕后别的线程才能读取该资源,这叫线程的互斥。我们需要使用synchronized来给共享区域加锁,确保共享资源安全。
实现代码:
package com.zhangyufan.thread;
public class TestPrinter {
public static void main(String[] args) {
Printer p = new Printer();
MaterialPrint mp1 = new MaterialPrint("小王", p);
MaterialPrint mp2 = new MaterialPrint("小李", p);
MaterialPrint mp3 = new MaterialPrint("小陈", p);
mp1.start();
mp2.start();
mp3.start();
try {
mp1.join();
mp2.join();
mp3.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("打印完毕,打印的总材料数为:" + p.count);
}
}
class Printer {
public int count = 0;
public synchronized void print() {
for (int i = 1; i <= 10; i++) {
System.out.println("正在执行" + Thread.currentThread().getName() + "的第" + i + "次打印,已打印材料总数为:" + (count++));
try {
Thread.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class MaterialPrint extends Thread {
private Printer p = null;
public MaterialPrint(String name, Printer p) {
super(name);
this.p = p;
}
@Override
public void run() {
p.print();
}
}
运行结果:
我们可以发现,在只有一台打印机的情况下,三个人的打印线程同时启动,谁的打印线程先抢到,就先完成谁的打印任务,等完成了某一个人的打印任务之后,再等待下一个抢到的打印线程并完成相应的打印任务。如此一来,并不会出现打印错乱等问题,实现了线程互斥。
2.选定两款手机,一款是使用ios系统的苹果手机,一款是使用鸿蒙系统的华为手机。在某商场的苹果手机专卖店和华为手机专卖店中一直有消费者在购买苹果手机和华为手机。根据两家手机专卖店的近期生意状况,一直会有消费者前来购买,也就意味着一直需要生产这两款手机。消费者的购买行为和厂家生产这两款手机的行为不形成冲突,生产和消费过程中形成了线程同步,需要共享数据。使用相关方法编写一个程序处理该线程同步问题。其中包含有手机类Phone,定义了名称和使用的系统,表示某款手机,提供生产手机和购买手机的操作production()和getProduct()。需要定义生产者类Productor,实现Runnable接口,重写run()方法,调用生产手机的操作,需要定义消费者类Consumer,实现Runnable接口,重写run()方法,调用购买手机的操作。在测试类中创建手机对象作为共享数据区域,创建生产者对象,消费者对象,创建两个线程并启动。
这里说明一下有关线程同步:
在某些情况下,线程需要交替执行。比如一个线程向一个存储单元执行存放数据,而另一个操作执行取值操作,线程间同步完成这个存取任务,需要将这些线程同步。要解决线程交替执行但是又要保证共享资源安全,这需要使用到Java的3个方法:wait()、notify()和notifyAll(),这3个方法是Object类的成员方法,所以在任何类中都可以使用这3个方法。
实现代码:
package com.zhangyufan.thread;
public class TestProductorConsumer {
public static void main(String[] args) throws InterruptedException {
Phone p = new Phone();
Productor pro = new Productor(p);
Consumer con = new Consumer(p);
new Thread(pro).start();
new Thread(con).start();
Thread.sleep(20000);
System.out.println("生产者共生产了" + (p.i + p.j) + "台手机");
System.out.println("消费者共购买了" + (p.i + p.j) + "台手机");
}
}
class Phone {
private String name = "苹果手机";
private String system = "ios系统";
private boolean flag = true;
public int i = 0;
public int j = 0;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSystem() {
return system;
}
public void setSystem(String system) {
this.system = system;
}
public synchronized void production(String name, String system) {
if (!flag) {
try {
super.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
this.setName(name);
try {
Thread.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
this.setSystem(system);
if (this.getName().equals("苹果手机")) {
System.out
.println("生产了一部" + this.getName() + "---" + this.getSystem() + "---手机编号:" + this.getName() + (++i));
} else {
System.out
.println("生产了一部" + this.getName() + "---" + this.getSystem() + "---手机编号:" + this.getName() + (++j));
}
flag = false;
super.notify();
}
public synchronized void getProduct() {
if (flag) {
try {
super.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
try {
Thread.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("消费者买走了一部" + this.getName());
flag = true;
super.notify();
}
}
class Productor implements Runnable {
private Phone p = null;
public Productor(Phone p) {
this.p = p;
}
@Override
public void run() {
for (int i = 0; i < 30; i++) {
if (i % 2 != 0) {
this.p.production("苹果手机", "ios系统");
} else {
this.p.production("华为手机", "鸿蒙系统");
}
}
}
}
class Consumer implements Runnable {
private Phone p = null;
public Consumer(Phone p) {
this.p = p;
}
@Override
public void run() {
for (int i = 0; i < 30; i++) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
this.p.getProduct();
}
}
}
运行结果:
我们可以发现,在这里厂家生产手机与消费者购买手机的行为没有形成冲突,生产手机与购买手机的过程体现了线程同步,最终实现了题目要求。