(一)项目框架分析
对于学生并发接水项目,根据面向对象的思想,需要创建两个对象,即学生和水龙头。
接下来主要讲解不排队接水和排队接水两张情况。
项目的目录文件如下:
(二)不排队接水
假设有四个学生小常、小尚、小王和小刘下课之后去接水。由于水房中只要一个水龙头,所以,谁先去,谁先接水,谁先回教室。
Water.java类用来模拟现实生活中的水龙头,水龙头具有流水的功能,所以该类中有一个流水的方法flowWater,具体代码如下:
package com.cjg.noqueue; public class Water { public void flowWater(String studentName){ System.out.println("开始为"+studentName+"流水"); try{ Thread.sleep(3000); //线程休眠 } catch(InterruptedException e){ e.printStackTrace(); } System.out.println("结束为"+studentName+"流水"); } }
Student.java类用来模拟现实生活中的学生,由于学生要实现并发接水的功能,所以接水的代码全部放在run() 方法里,具体代码如下:
package com.cjg.noqueue; public class Student extends Thread { private String studentName; private Water water; public Student(String studentName ,Water water){ super(); this.studentName = studentName; this.water=water; } public void receiveWater(){ System.out.println(studentName+"从教室跑向饮水机"); water.flowWater(studentName); System.out.println(studentName+"跑回教师"); } public void run(){ receiveWater(); } }
TestWater.java类用来测试学生和水龙头的类,是否实现了不排队接水的功能,具体代码如下:
package com.cjg.noqueue; public class TestWater { public static void main(String[] args){ Water water =new Water(); Student xiaochang = new Student("小常",water); Student xiaoshang=new Student("小尚",water); Student xiaowang=new Student("小王",water); Student xiaoliu=new Student("小刘",water); xiaochang.start(); xiaoshang.start(); xiaowang.start(); xiaoliu.start(); } }
程序运行结果
小常从教室跑向饮水机
小尚从教室跑向饮水机
小王从教室跑向饮水机
小刘从教室跑向饮水机
开始为小刘流水
开始为小王流水
开始为小尚流水
开始为小常流水
结束为小刘流水
结束为小常流水
结束为小王流水
小王跑回教师
结束为小尚流水
小尚跑回教师
小常跑回教师
小刘跑回教师
(三)排队接水
Water.java类的代码如下:
package com.cjg.queue; public class Water { int studentNumber; public synchronized void flowWater(String studentName){ synchronized (this){ ++studentNumber; System.out.println("开始为"+studentName+"流水"); try{ Thread.sleep(3000); //线程休眠 } catch(InterruptedException e){ e.printStackTrace(); } System.out.println("结束为"+studentName+"流水"); if(studentNumber<4){ try{ wait(); } catch(InterruptedException e){ e.printStackTrace(); } }else{ notifyAll(); } } } }
Student.java类的具体代码如下:
package com.cjg.queue; import com.cjg.noqueue.Water; public class Student extends Thread { private String studentName; private Water water; public Student(String studentName ,Water water){ super(); this.studentName = studentName; this.water=water; } public void receiveWater(){ System.out.println(studentName+"从教室跑向饮水机"); water.flowWater(studentName); System.out.println(studentName+"跑回教师"); } public void run(){ receiveWater(); } }
Student.java类的代码和不排队接水的代码相同。
代码运行结果:
小常从教室跑向饮水机
小王从教室跑向饮水机
小尚从教室跑向饮水机
开始为小王流水
开始为小常流水
小刘从教室跑向饮水机
开始为小刘流水
开始为小尚流水
结束为小常流水
结束为小刘流水
小刘跑回教师
结束为小尚流水
结束为小王流水
小尚跑回教师
小常跑回教师
小王跑回教师
(四)java多线程thread
进程是程序在处理机中的一次运行。一个进程既包括其所要执行的指令,也包括了执行指令所需的系统资源,不同进程所占用的系统资源相对独立。所以进程是重量级的任务,它们之间的通信和转换都需要操作系统付出较大的开销。
线程是进程中的一个实体,是被系统独立调度和分派的基本单位。线程自己基本上不拥有系统资源,但它可以与同属一个进程的其他线程共享进程所拥有的全部资源。所以线程是轻量级的任务,它们之间的通信和转换只需要较小的系统开销。
Java支持多线程编程,因此用Java编写的应用程序可以同时执行多个任务。Java的多线程机制使用起来非常方便,用户只需关注程序细节的实现,而不用担心后台的多任务系统。
Java语言里,线程表现为线程类。Thread线程类封装了所有需要的线程操作控制。在设计程序时,必须很清晰地区分开线程对象和运行线程,可以将线程对象看作是运行线程的控制面板。在线程对象里有很多方法来控制一个线程是否运行,睡眠,挂起或停止。线程类是控制线程行为的唯一的手段。一旦一个Java程序启动后,就已经有一个线程在运行。可通过调用Thread.currentThread方法来查看当前运行的是哪一个线程。
JAVA中创建线程可以通过继承Thread类和实现Runnable接口来创建一个线程。
继承Thread类
class MyThread extends Thread{ ..... @Override public void run(){ } } MyThread mt=new MyThread(); mt.start();
实现Runnable接口
class MyThread implements Runnable{ .... @Override public void run(){ } } MyThread mt=new MyThread(); Thread td=new Thread(mt); sd.start();