以前: 多个线程操作共享数据,线程任务是相同的
现在: 多个线程操作共享数据,线程任务不相同
要求: 生产一个,消费一个,再生产一个,再消费一个
解决唤醒报异常的问题-- 线程通信等待唤醒 wait() notify() notifyAll()
public class BaoZi04 {
private int num;
private boolean flag;
public synchronized void xiaoFei() {
if (flag == false) {
try {wait();}catch (Exception e){e.printStackTrace();}
}
String threadName = Thread.currentThread().getName();
System.out.println(threadName+"消费第~~~~~~"+num+"~~~~~~个包子");
flag = false;
notify();
}
public synchronized void shengChan() {
if(flag == true) {
try {wait();}catch (Exception e){e.printStackTrace();}
}
num++;
String threadName = Thread.currentThread().getName();
System.out.println(threadName+"生产第..."+num+"...个包子");
flag = true;
notify();
}
public boolean getFlag() {
return flag;
}
public void setFlag(boolean flag) {
this.flag = flag;
}
}
public class Producer04 implements Runnable{
private BaoZi04 bz;
public Producer04(BaoZi04 bz) {
this.bz = bz;
}
@Override
public void run() {
while (true)
bz.shengChan();
}
}
public class Consumer04 implements Runnable{
private BaoZi04 bz;
public Consumer04(BaoZi04 bz) {
this.bz = bz;
}
@Override
public void run() {
while (true)
bz.xiaoFei();
}
}
public class Demo04PC {
public static void main(String[] args) {
BaoZi04 bz = new BaoZi04();
Producer04 pTask = new Producer04(bz);
Consumer04 cTask = new Consumer04(bz);
Thread pThread = new Thread(pTask, "生产者线程");
Thread cThread = new Thread(cTask, "消费者线程");
pThread.start();
cThread.start();
}
}
线程池Thread Pool
线程频繁的创建和销毁线程,会降低效率 所以需要使用线程池
Callable call 可以throws,可以try-catch
runnable submit只能内部try-catch
都有返回值Future 封装结果数据的 get(): 获取Future封装的结果数据
创建线程池对象(有3个线程对象): 工具类Executors调用静态方法
ExecutorService pool = Executors.newFixedThreadPool(3); 创建线程池
shutDown():关闭线程池
线程池的练习计算1-100的和
实现步骤:
1.创建代表线程任务的Callable接口的实现类
2.Callable接口的实现类覆盖重写抽象方法call,计算1到100的数字之和
3.创建线程池对象,指定线程数量
4.创建多个线程任务对象
5.线程池对象调用submit方法执行线程任务对象获取结果Future对象
6.打印结果Future对象中封装的具体结果
*/ //执行submit方法指定的Runnable接口类型的线程任务
Future<?> future = pool.submit(task01);
//执行submit方法指定的Callable接口类型的线程任务
public class Demo07ThreadPoolSum {
public static void main(String[] args) throws ExecutionException, InterruptedException {
//3.创建线程池对象,指定线程数量
ExecutorService pool = Executors.newFixedThreadPool(3);
//4.创建多个线程任务对象
MySumTask task100 = new MySumTask(1, 100);//计算1-100数字之和的线程任务
MySumTask task200 = new MySumTask(1, 200);//计算1-200数字之和的线程任务
MySumTask task300 = new MySumTask(1, 300);//计算1-300数字之和的线程任务
//3.从线程池对象pool中获取一个线程对象(至于获取到的哪个线程对象,不用管)
//执行submit方法指定的Callable接口类型的线程任务
//任务执行完毕,线程对象会返还池中,怎么返还的,不用关心
//5.线程池对象调用submit方法执行线程任务对象获取结果Future对象
Future<Integer> f = pool.submit(task100);
//6.打印结果Future对象中封装的具体结果
System.out.println(f.get());
f = pool.submit(task200);
//6.打印结果Future对象中封装的具体结果
System.out.println(f.get());
f = pool.submit(task300);
//6.打印结果Future对象中封装的具体结果
System.out.println(f.get());
}
}
//创建Runnable接口的实现类
public class MyCallable04 implements Callable<Integer> {
@Override
public Integer call() throws Exception {
Random r = new Random();
return Math.abs(r.nextInt());//返回一个正的int范围内的数字
}
}
/*
计算1-100的数字之和的线程任务
*/
public class MySumTask implements Callable<Integer> {
private int start;
private int end;
public MySumTask(int start, int end) {
this.start = start;
this.end = end;
}
@Override
public Integer call() throws Exception {
int sum = 0;
for (int i = start; i <= end; i++) {
sum += i;
}
return sum;
}
}