• 第九周课程总结&实验报告(七)


    实验七

    实验任务详情:

    完成火车站售票程序的模拟。
    要求:
    (1)总票数1000张;
    (2)10个窗口同时开始卖票;
    (3)卖票过程延时1秒钟;
    (4)不能出现一票多卖或卖出负数号票的情况;

    实验源码:

    package 火车站卖票;
    
    class MyThread implements Runnable{                  
        private int ticket=1000;
        public void run() {                                           
            for(int i=0;i<100;i++) {
                synchronized(this) {                            
                    if(ticket>0) {                                  
                    	try {
                            Thread.sleep(100);        
                        }
                        catch(InterruptedException e) {
                            e.printStackTrace();
                        }
                        System.out.println(Thread.currentThread().getName()+"售出,剩余票数:"+--ticket);    
                    }
                }
            }
        }
    }
    

    运行代码

    package 火车站卖票;
    
    public class run{
        public static void main(String[] args) {
             MyThread save=new MyThread();       
             new Thread(save,"窗口1").start();                
             new Thread(save,"窗口2").start();
             new Thread(save,"窗口3").start();
             new Thread(save,"窗口4").start();
             new Thread(save,"窗口5").start();
             new Thread(save,"窗口6").start();
             new Thread(save,"窗口7").start();
             new Thread(save,"窗口8").start();
             new Thread(save,"窗口9").start();
             new Thread(save,"窗口10").start();
        }
    }
    

    实验截图

    问题

    运行的过程中,发现每个窗口会运行一百次再去随机另外的窗口,不知道怎么解决。
    希望在以后的学习中能学习到解决这个问题的方法!!
    似乎是优先级的问题!!

    学习总结

    线程操作我们可以通过Thread类和Runnable类来实现

    Thread类实现了Runnable接口。
    在Thread类中,有一些比较关键的属性,比如name是表示Thread的名字,可以通过Thread类的构造器中的参数来指定线程名字,priority表示线程的优先级(最大值为10,最小值为1,默认值为5),daemon表示线程是否是守护线程,target表示要执行的任务。

    线程运行状态的几个方法:
    1)start方法
    start()用来启动一个线程,当调用start方法后,系统才会开启一个新的线程来执行用户定义的子任务,在这个过程中,会为相应的线程分配需要的资源。
    2)run方法
    run()方法是不需要用户来调用的,当通过start方法启动一个线程之后,当线程获得了CPU执行时间,便进入run方法体去执行具体的任务。注意,继承Thread类必须重写run方法,在run方法中定义具体要执行的任务。
    3)sleep方法
    sleep方法有两个重载版本!!!
    (4)线程的礼让(Thread.yield())方法

    线程的同步方法:在方法声明上加上synchronized

    public synchronized void method(){
    可能会产生线程安全问题的代码
    }  
    同步方法中的锁对象是 this(即调用者对象)
    静态同步方法: 在方法声明上加上static synchronized
    public static synchronized void method(){
    可能会产生线程安全问题的代码
    }
    静态同步方法中的锁对象是 类名.class(因为在加载类文件的时候,静态同步方法由于是静态的也被加载进内存了,类名.class的加载优先级高于静态方法)
    同步代码块:在需要同步的代码外面包上一个synchronized
    (Object o){
    可能会产生线程安全问题的代码
    } 

    同步代码块中的所对象可以是任意对象!!!

    线程的死锁

    同步锁使用的弊端:当线程任务中出现了多个同步(多个锁)时,如果同步中嵌套了其他的同步。这时容易引发一种现象:程序出现无限等待,这种现象我们称为死锁。这种情况能避免就避免掉。

  • 相关阅读:
    软件测试系列--集成测试
    软件测试系列--系统测试
    软件测试系列-软件质量
    Java初认识--函数和数组
    Java初认识--Java中的语法结构
    Java初认识--Java语言的书写规范及基本的运算符
    Java初认识--环境搭建及基本数据类型
    软件测试系列--软件缺陷管理
    ASP.NET MVC 路由系统类
    由浅入深了解Retrofit(一)
  • 原文地址:https://www.cnblogs.com/songzhihaoT1/p/11738823.html
Copyright © 2020-2023  润新知