Java——第七章(进程和多线程)—项目案例

    xiaoxiao2021-12-13  18

    1、之前有做过打印图形的程序,现在要通过两个线程对象打印出三角形和矩形,要求两

    个图形不能错乱。

    三角形Thread:

    public class SanjiaoThread implements Runnable{ private int hang=5; private Object o ; @Override public void run() { // TODO Auto-generated method stub synchronized (o) { for (int i = 0; i < hang; i++) { for (int j = 0; j < hang-i-1; j++) { System.out.print(" "); } for (int j = 0; j < 2*i+1; j++) { System.out.print("*"); } System.out.println(); } } } public int getHang() { return hang; } public void setHang(int hang) { this.hang = hang; } public Object getO() { return o; } public void setO(Object o) { this.o = o; } }

    矩形Thread:

    public class JuXingThread implements Runnable{ private Object o ; @Override public void run() { // TODO Auto-generated method stub synchronized (o) { SanjiaoThread st = new SanjiaoThread(); for (int i = 0; i < st.getHang(); i++) { for (int j = 0; j < st.getHang()*2; j++) { System.out.print("*"); } System.out.println(); } } } public Object getO() { return o; } public void setO(Object o) { this.o = o; } }

    测试类:

    public class Test02 { public static void main(String[] args) throws Exception { // TODO Auto-generated method stub Object o = new Object(); SanjiaoThread st = new SanjiaoThread(); st.setO(o); Thread t = new Thread(st,"三角形: "); JuXingThread jt = new JuXingThread(); jt.setO(o); Thread t1 =new Thread(jt,"矩形: "); t.start(); t1.start(); } }

    通常可以在线程类里面定义要锁定的资源对象,通过主线程中创建该资源对象,通过赋

    值给哪个线程,哪个线程获得资源的拥有权进行操作。

    2、有一个男生叫晓军,在双十一这天要取银行卡里5000中的3000,然而他媳妇正好购物

    车中放了3000块钱的包包和衣服,俩人同时取钱,要求一人取出后另一个人账号小于

    3000取不出来,解决线程同步问题。

    线程类:

    public class QuqianRun1 extends Thread{ private static Integer money=5000; boolean flag = false; @Override public void run() { synchronized (money) { if(flag) { if(money>3000) { try { Thread.sleep(1000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+": 能取钱了!"); money-=3000; System.out.println(Thread.currentThread().getName()+"剩余:"+money); } }else{ if(money>3000) { System.out.println(Thread.currentThread().getName()+": 能花钱了!"); money-=3000; System.out.println(Thread.currentThread().getName()+"剩余:"+money); } } } } public boolean isFlag() { return flag; } public void setFlag(boolean flag) { this.flag = flag; } }

    测试类:

    public class Test04 { public static void main(String[] args) { // TODO Auto-generated method stub QuqianRun1 qr = new QuqianRun1(); qr.setName("晓军"); qr.setFlag(true); QuqianRun1 qr1 = new QuqianRun1(); qr1.setName("他媳妇"); qr1.setFlag(false); qr.start(); qr1.start(); } }

    这个是随机运行,两个线程不一定轮到谁,多试几次。。结果就会不一样。

    3、电影票购买,分为到店买和网上购买,最近上映的《奇异博士》,晚场票量一共500

    张,两种购买方式不冲突,低于0张不可购买。

    线程类:

    import java.util.Scanner; public class DianYingPiao extends Thread{ // private Object o; private static Integer count=500; private boolean b =true; private int zhang =0; @Override public void run() { // TODO Auto-generated method stub if(b) { synchronized (count) { System.out.println("输入到店要买的张数:"); Scanner sc = new Scanner(System.in); zhang =sc.nextInt(); if(count>=zhang) { count-=zhang; System.out.println("成功购买"+zhang+"张电影票!剩余"+count+"张。"); } else{ System.out.println("余量不足!"); } } }else { synchronized (count) { System.out.println("输入网上要买的张数:"); Scanner sc = new Scanner(System.in); zhang =sc.nextInt(); if(count>=zhang) { count-=zhang; System.out.println("成功购买"+zhang+"张电影票!剩余"+count+"张。"); } else{ System.out.println("余量不足!"); } } } } public boolean isB() { return b; } public void setB(boolean b) { this.b = b; } // public Object getO() { // return o; // } // public void setO(Object o) { // this.o = o; // } }

    测试类:

    public class Test07 { public static void main(String[] args) { // TODO Auto-generated method stub // Object o = new Object(); DianYingPiao dyp1 = new DianYingPiao(); DianYingPiao dyp2 = new DianYingPiao(); dyp2.setB(false); // dyp1.setO(o); // dyp2.setO(o); dyp1.start(); dyp2.start(); } }

    线程类和测试类中注释的地方第二种解决线程同步问题方法,通过主类设置给哪个线程

    上锁资源进行操作。使用这种方式需要在synchronized中改成object对象o,而不是

    count。

    4.科学家吃饭问题,5个科学家吃饭,每个人只有一只筷子,要想吃到饭,必须用两只筷

    子,但是如果每个人都要等其中 一个人贡献出来自己的筷子,都吃不上饭,只要有一个

    人贡献出来,大家都可以吃到饭。这就是科学家吃饭问题,这里为了更好演示,举例2个

    人吃饭。

    第二个人的线程:

    public class Thread2 extends Thread{ private Object o1; private Object o2; @Override public void run() { // TODO Auto-generated method stub synchronized (o2) { System.out.println("我已经有我一只筷子了,再给我一只呗!"); synchronized (o1) { System.out.println("我终于要开吃啦!"); o1.notify();//唤醒之前的线程wait方法。使其获得时间片。 } } }

    第一个人的线程:

    public class Thread1 extends Thread{ private Object o1; private Object o2; @Override public void run() { // TODO Auto-generated method stub synchronized (o1) { try { o1.wait();//放在synchronized结构内使用。将o1所有权给释放给下个线程 } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println("给我筷子,你哥我要吃饭!"); synchronized (o2) { System.out.println("终于吃到饭了!"); } } } public Thread1(Object o1, Object o2) { super(); this.o1 = o1; this.o2 = o2; } }

    测试类:

    public class Test06 { public static void main(String[] args) throws Exception { // TODO Auto-generated method stub Object o1 = new Object(); Object o2 = new Object(); Thread1 t1 = new Thread1(o1, o2); Thread2 t2 = new Thread2(o1, o2); t1.start(); t2.start(); } }

    这样是第一个人先贡献自己的筷子,永远第二个人先吃饭,然后第一个人再吃。

    5、介绍一下好玩的类TimerTast(计时器任务)—Timer(计时器),通过创建Timer

    类对象调用schedule方法,来定时做一些事情,例如闹钟嘛、、

    代码:

    import java.awt.Toolkit; import java.util.Date; import java.util.Timer; import java.util.TimerTask; public class Timermain { public static void main(String[] args) throws Exception { // TODO Auto-generated method stub Timer timer = new Timer(); Date time = new Date(System.currentTimeMillis()+5000); timer.schedule(new TimerTask() { @Override public void run() { // TODO Auto-generated method stub Toolkit.getDefaultToolkit().beep(); } }, time, 500); timer.scheduleAtFixedRate(new TimerTask() { @Override public void run() { // TODO Auto-generated method stub } }, 5000, 600); Thread.sleep(10000); timer.cancel(); } }

    schedule(TimerTask task, Date firstTime, long period) ;

    这个方法中第一个是TimerTask的一个对象,第二个参数是开始的时间,第三个参数是

    间隔时间。

    可以是向上面的匿名内部类之间在main中创建task,也可以在外面建一个TimerTast

    类,传入其对象都可以。匿名内部类在Android中经常用到,方便。

    run方法就是到点时要执行的操作,Toolkit.getDefaultToolkit().beep();是调用电脑系

    统默认声音。。

    转载请注明原文地址: https://ju.6miu.com/read-950223.html

    最新回复(0)