内容学习于:edu.aliyun.com
1. 数字加减
设计4个线程对象,两个线程执行减操作,两个线程执行加操作。
代码:
class AddThread implements Runnable {
private Resource resource;
public AddThread(Resource resource) {
this.resource = resource;
}
@Override
public void run() {
for (int i = 0; i < 5; i++) {
try {
this.resource.add();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class SubThread implements Runnable {
private Resource resource;
public SubThread(Resource resource) {
this.resource = resource;
}
@Override
public void run() {
for (int i = 0; i < 5; i++) {
try {
this.resource.sub();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class Resource {//定义操作的资源
private volatile int num = 0;//被进行操作的数据
private boolean flag = true;//表示允许的操作
//flag = true,表示允许加法,不允许减法
//flag = flase,表示允许减法,不允许加法
public synchronized void add() throws InterruptedException {//同步加法操作
if (this.flag == false) {//如果不允许加法,则该线程等待
super.wait();
}
Thread.sleep(100);
this.num++;
System.out.println("【加法操作-" + Thread.currentThread().getName() + "】" + "num=" + this.num);
this.flag = false;//执行完加法,将允许减法不允许加法
super.notifyAll();//唤醒所有等待线程
}
public synchronized void sub() throws InterruptedException {//同步减法操作
if (this.flag == true) {//如果不允许减法,则该线程等待
super.wait();
}
Thread.sleep(200);
this.num--;
System.out.println("【减法操作-" + Thread.currentThread().getName() + "】" + "num=" + this.num);
this.flag = true;//执行完减法,将允许加法不允许减法
super.notifyAll();//唤醒所有等待线程
}
}
public class ThreadDemo {
public static void main(String[] args) {
Resource resource = new Resource();
AddThread at = new AddThread(resource);
SubThread st = new SubThread(resource);
new Thread(at, "加法线程-A").start();
new Thread(at, "加法线程-B").start();
new Thread(st, "减法线程-X").start();
new Thread(st, "减法线程-Y").start();
}
}
结果:
【加法操作-加法线程-A】num=1
【减法操作-减法线程-X】num=0
【加法操作-加法线程-B】num=1
【减法操作-减法线程-X】num=0
【加法操作-加法线程-B】num=1
【减法操作-减法线程-X】num=0
【加法操作-加法线程-B】num=1
【减法操作-减法线程-X】num=0
【加法操作-加法线程-B】num=1
【减法操作-减法线程-X】num=0
【加法操作-加法线程-B】num=1
【减法操作-减法线程-Y】num=0
【加法操作-加法线程-A】num=1
【减法操作-减法线程-Y】num=0
【加法操作-加法线程-A】num=1
【减法操作-减法线程-Y】num=0
【加法操作-加法线程-A】num=1
【减法操作-减法线程-Y】num=0
【加法操作-加法线程-A】num=1
【减法操作-减法线程-Y】num=0
这一题目是一个经典的多线程的开发操作,这一个程序里面一定要考虑的核心本质在于:加一个、减一个,<mark>整体的计算结果应该只在0、-1、1之间循环出现。</mark>
2. 生产电脑
设计一个生产电脑和搬运电脑类,要求生产出一台电脑就搬走一台电脑,如果没有新的电脑生产出来,则搬运工要等待新电脑产出;如果生产出的电脑没有搬走,则要等待电脑搬走之后再生产,并统计出生产的电脑数量。在本程序之中实现的就是一个标准的生产者与消费者的处理模型,那么下面实现具体的程序代码。
代码:
class Producer implements Runnable {//生产者线程
private Resource resource;
public Producer(Resource resource) {
this.resource = resource;
}
@Override
public void run() {
for (int i = 0; i < 5; i++) {
try {
this.resource.make();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class Customer implements Runnable {//生产者线程
private Resource resource;
public Customer(Resource resource) {
this.resource = resource;
}
@Override
public void run() {
for (int i = 0; i < 5; i++) {
try {
this.resource.get();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class Computer {
private static int count;
private String name;
private double price;
public Computer(String name, double price) {
this.name = name;
this.price = price;
count++;
}
@Override
public String toString() {
return "【第" + count + "台电脑】" + "、电脑名字:" + this.name + "、电脑价格:" + this.price;
}
}
class Resource {
private Computer computer;
public synchronized void make() throws InterruptedException {
if (this.computer != null) {//已经生产过了
super.wait();
}
Thread.sleep(100);
this.computer = new Computer("Xzzz", 2020.0);
System.out.println("【生产电脑】" + this.computer);
super.notifyAll();
}
public synchronized void get() throws InterruptedException {
if (computer == null) {//还未生产
super.wait();
}
Thread.sleep(10);
System.out.println("【取走电脑】" + this.computer);
this.computer = null;//电脑已经被消费走
super.notifyAll();
}
}
public class ThreadDemo {
public static void main(String[] args) {
Resource resource = new Resource();
new Thread(new Producer(resource)).start();
new Thread(new Customer(resource)).start();
}
}
结果:
【生产电脑】【第1台电脑】、电脑名字:Xzzz、电脑价格:2020.0
【取走电脑】【第1台电脑】、电脑名字:Xzzz、电脑价格:2020.0
【生产电脑】【第2台电脑】、电脑名字:Xzzz、电脑价格:2020.0
【取走电脑】【第2台电脑】、电脑名字:Xzzz、电脑价格:2020.0
【生产电脑】【第3台电脑】、电脑名字:Xzzz、电脑价格:2020.0
【取走电脑】【第3台电脑】、电脑名字:Xzzz、电脑价格:2020.0
【生产电脑】【第4台电脑】、电脑名字:Xzzz、电脑价格:2020.0
【取走电脑】【第4台电脑】、电脑名字:Xzzz、电脑价格:2020.0
【生产电脑】【第5台电脑】、电脑名字:Xzzz、电脑价格:2020.0
【取走电脑】【第5台电脑】、电脑名字:Xzzz、电脑价格:2020.0
3. 竞争抢答
实现一个竞拍抢答程序:要求设置三个抢答者(三个线程),而后同时发出抢答指令,抢答成功者给出成功提示,未抢答成功者给出失败提示。
<mark>对于这一个多线程的操作由于里面需要牵扯到数据的返回问题,那么现在最好使用的Callable是比较方便的一种处理形式。</mark>
代码:
class MyThread implements Callable<String> {
private boolean flag = false;//抢答处理
@Override
public String call() throws Exception {
synchronized (this) {
if (flag == false) {//抢答成功
Thread.sleep(100);
this.flag = true;
return Thread.currentThread().getName() + "强答成功";
} else {
return Thread.currentThread().getName() + "强答失败";
}
}
}
}
public class ThreadDemo {
public static void main(String[] args) throws ExecutionException, InterruptedException {
MyThread mt = new MyThread();
FutureTask<String> taskA = new FutureTask<>(mt);
FutureTask<String> taskB = new FutureTask<>(mt);
FutureTask<String> taskC = new FutureTask<>(mt);
new Thread(taskA, "竞赛者A").start();
new Thread(taskB, "竞赛者B").start();
new Thread(taskC, "竞赛者C").start();
System.out.println(taskA.get());
System.out.println(taskB.get());
System.out.println(taskC.get());
}
}
结果:
竞赛者A强答失败
竞赛者B强答成功
竞赛者C强答失败