1、数字加减
设计4个线程对象,两个线程执行减操作,两个线程执行加操作。
范例:程序代码如下
package cn.demos;
//定义一个操作的资源
class Resoure {
// 定义一个要进行加减操作的数据
private int num = 0;
// 加减的切换
// 如果flag等于true,表示进行加法操作,不能进行减法操作;
// 如果flag等于false,表示进行减法操作,不能进行加法操作;
private boolean flag = true;
// 执行加法操作
public synchronized void add() throws Exception {
if (this.flag == false) {// 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 Exception {
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();
}
}
// 准备一个加线程
class AddThread implements Runnable {
// 引入Resource
private Resoure resoure;
public AddThread(Resoure resoure) {
this.resoure = resoure;
}
@Override
public void run() {
for (int x = 0; x < 50; x++) {
try {
this.resoure.add();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
// 准备一个减线程
class SubThread implements Runnable {
// 引入Resource
private Resoure resoure;
public SubThread(Resoure resoure) {
this.resoure = resoure;
}
@Override
public void run() {
for (int x = 0; x < 50; x++) {
try {
this.resoure.sub();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
public class ThreadDemo1 {
public static void main(String[] args) {
Resoure res = new Resoure();
// 加法线程
AddThread at = new AddThread(res);
// 减法线程
SubThread st = new SubThread(res);
new Thread(at, "加法线程 - A").start();
new Thread(at, "加法线程 - B").start();
new Thread(st, "减法线程 - C").start();
new Thread(st, "减法线程 - D").start();
}
}
执行结果(部分) | 加法操作!!!!加法线程 - B===num==1 减法操作!!!!减法线程 - C===num==0 加法操作!!!!加法线程 - B===num==1 减法操作!!!!减法线程 - D===num==0 加法操作!!!!加法线程 - A===num==1 减法操作!!!!减法线程 - D===num==0 加法操作!!!!加法线程 - B===num==1 减法操作!!!!减法线程 - C===num==0 加法操作!!!!加法线程 - B===num==1 减法操作!!!!减法线程 - D===num==0 加法操作!!!!加法线程 - A===num==1 减法操作!!!!减法线程 - D===num==0 加法操作!!!!加法线程 - B===num==1 减法操作!!!!减法线程 - C===num==0 加法操作!!!!加法线程 - B===num==1 |
从执行结果来看,可以得知,四个线程交替执行,执行结果在1和0和-1之间反复横跳。
2、生产电脑
设计一个生产电脑和搬运电脑类,要求生产出一台电脑就搬走一台电脑,如果没有新的电脑生产出来则搬运工要等待新电脑产出;如果生产出的电脑没有搬走,则要等待电脑搬走之后再生产,并统计出生产的电脑数量。
范例:具体实现代码
package cn.demos;
class Computer {
// 表示生产的个数
private static int count = 0;
// 电脑名字
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 + "台" + "computer [name=" + this.name + ", price=" + price + "]";
}
}
class Resource {
// 定义一个标记
private boolean flag = true;
private Computer computer;
// 生产电脑
public synchronized void make() throws Exception {
if (this.computer != null) {// 已经生产过了
super.wait();
}
Thread.sleep(100);
this.computer = new Computer("DELL牌", 10000);
System.out.println("生产电脑" + this.computer);
super.notifyAll();
}
// 获得电脑
public synchronized void get() throws Exception {
if (this.computer == null) {// 没有生产过
super.wait();
}
Thread.sleep(100);
System.out.println(this.computer);
System.out.println("取走电脑" + this.computer);
// 将computer的值设置为null,表示已经取走了电脑
this.computer = null;
super.notifyAll();
}
}
// 生产者线程
class Producer1 implements Runnable {
private Resource resource;
public Producer1(Resource resource) {
this.resource = resource;
}
@Override
public void run() {
for (int x = 0; x < 50; x++) {
try {
this.resource.make();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
// 消费者线程
class Consumer1 implements Runnable {
private Resource resource;
public Consumer1(Resource resource) {
this.resource = resource;
}
@Override
public void run() {
for (int x = 0; x < 50; x++) {
try {
this.resource.get();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
public class ThreadDemo1 {
public static void main(String[] args) {
Resource res = new Resource();
new Thread(new Producer1(res)).start();
new Thread(new Consumer1(res)).start();
}
}
代码执行结果部分展示 | 生产电脑第1台computer [name=DELL牌, price=10000.0] 第1台computer [name=DELL牌, price=10000.0] 取走电脑第1台computer [name=DELL牌, price=10000.0] 生产电脑第2台computer [name=DELL牌, price=10000.0] 第2台computer [name=DELL牌, price=10000.0] 取走电脑第2台computer [name=DELL牌, price=10000.0] 生产电脑第3台computer [name=DELL牌, price=10000.0] 第3台computer [name=DELL牌, price=10000.0] 取走电脑第3台computer [name=DELL牌, price=10000.0] 生产电脑第4台computer [name=DELL牌, price=10000.0] 第4台computer [name=DELL牌, price=10000.0] 取走电脑第4台computer [name=DELL牌, price=10000.0] 生产电脑第5台computer [name=DELL牌, price=10000.0] 第5台computer [name=DELL牌, price=10000.0] 取走电脑第5台computer [name=DELL牌, price=10000.0] 生产电脑第6台computer [name=DELL牌, price=10000.0] 第6台computer [name=DELL牌, price=10000.0] 取走电脑第6台computer [name=DELL牌, price=10000.0] 生产电脑第7台computer [name=DELL牌, price=10000.0] 第7台computer [name=DELL牌, price=10000.0] 取走电脑第7台computer [name=DELL牌, price=10000.0] 生产电脑第8台computer [name=DELL牌, price=10000.0] 第8台computer [name=DELL牌, price=10000.0] 取走电脑第8台computer [name=DELL牌, price=10000.0] 生产电脑第9台computer [name=DELL牌, price=10000.0] 第9台computer [name=DELL牌, price=10000.0] 取走电脑第9台computer [name=DELL牌, price=10000.0] 生产电脑第10台computer [name=DELL牌, price=10000.0] 第10台computer [name=DELL牌, price=10000.0] 取走电脑第10台computer [name=DELL牌, price=10000.0] |
上面代码是一个典型的生产者与消费者案例模型。
3、竞争抢答
实现一个竞拍抢答程序:要求设置三个抢答者(三个线程),而后同时发出抢答指令,抢答成功者给出提示,未抢答成功者给出失败提示。
针对这个程序分析,这个程序里面牵扯到数据的返回问题,所以,在这里可以使用到我们前面提到的Callable来处理。
范例:程序实现代码
package cn.demos;
//多线程综合案例三:抢答问题的设计
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
class MyThread implements Callable<String> {
private boolean flag = false;// 抢答处理
@Override
public String call() throws Exception {
synchronized (this) {// 数据同步
if (this.flag == false) {// 抢答成功
this.flag = true;
return Thread.currentThread().getName() + "抢答成功";
} else {
return Thread.currentThread().getName() + "抢答失败";
}
}
}
}
public class ThreadDemo2 {
public static void main(String[] args) throws Exception {
MyThread mt = new MyThread();
FutureTask<String> taskA = new FutureTask<String>(mt);
FutureTask<String> taskB = new FutureTask<String>(mt);
FutureTask<String> taskC = new FutureTask<String>(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抢答失败 |