zoukankan      html  css  js  c++  java
  • 201871010112-梁丽珍《面向对象程序设计(java)》第十六周学习总结

     

    项目

    内容

    这个作业属于哪个课程

    https://www.cnblogs.com/nwnu-daizh/

    这个作业的要求在哪里

    https://www.cnblogs.com/nwnu-daizh/p/12031970.html

    作业学习目标

    (1) 掌握Java应用程序的打包操作;

    (2) 掌握线程概念;

    (3) 掌握线程创建的两种技术。

    (4) 学习设计应用程序的GUI。

    第一部分:总结教材14.1-14.3知识内容

    14.1 什么是线程

           多线程程序在较低的层次上扩展了多任务的概念:一个程序同时执行多个任务。通常,每一个任务称为一个线程( thread), 它是线程控制的简称。可以同时运行一个以上线程的程序称为多线程程序(multithreaded)。

    sleep 方法可以抛出一个 IntermptedException 异常。

    【API】java.Iang.Thread 1.0:

          static void sleep(long minis)

          休眠给定的毫秒数。

          参数: millis 休眠的毫秒数

    14.1.1 使用线程给其他任务提供机会

     下面是在一个单独的线程中执行一个任务的简单过程:
    1 ) 将任务代码移到实现了 Runnable 接口的类的 run 方法中。
    由于 Runnable 是一个函数式接口,可以用 lambda 表达式建立一个实例
      Runnable r = () -> { task code };
    2 ) 由 Runnable 创建一个 Thread 对象
      Thread t = new Thread(r);
    3 ) 启动线程
      t.start();

    注释: 也可以通过构建一个 Thread 类的子类定义一个线程 。然后, 构造一个子类的对象, 并调用 start 方法。 不过, 这种方法已不再推荐。 应该将要并行运行的任务与运行机制解耦合。如果有很多任务, 要为每个任务创建一个独立的线程所付出的代价太大了。 可以使用线程池来解决这个问题。

    警告: 不要调用 Thread 类或 Runnable 对象的 run 方法。 直接调用 run 方法, 只会执行同一个线程中的任务, 而不会启动新线程。 应该调用 Thread.start 方法。这个方法将创建一个执行 ran 方法的新线程

    【API】java.Iang.Thread 1.0:
      ThreadCRunnable target )
        构造一个新线程, 用于调用给定目标的 run() 方法。
      void start( )
        启动这个线程, 将引发调用 run() 方法。这个方法将立即返回, 并且新线程将并发运行。
      void run( )
        调用关联 Runnable 的 run 方法。
    【API】java.lang.Runnable 1.0:
      void run( )
        必须覆盖这个方法, 并在这个方法中提供所要执行的任务指令。
    14.2 中断线程
    在 Java 的早期版本中, 还有一个 stop方法, 其他线程可以调用它终止线程。但是, 这个方法现在已经被弃用了。
    没有可以强制线程终止的方法。然而, interrupt 方法可以用来请求终止线程。
    要想弄清中断状态是否被置位,首先调用静态的 Thread.currentThread 方法获得当前线程, 然后调用 islnterrupted 方法
    当在一个被阻塞的线程(调用 sleep 或 wait ) 上调用 interrupt 方法时, 阻塞调用将会被Interrupted Exception 异常中断。
    注释: 有两个非常类似的方法, interrupted 和 islnterrupted。Interrupted 方法是一个静态方法, 它检测当前的线程是否被中断。 而且, 调用 interrupted 方法会清除该线程的中断状态。 另一方面, islnterrupted 方法是一个实例方法, 可用来检验是否有线程被中断。调用这个方法不会改变中断状态。
    【API】java.Iang.Thread 1.0:
      void interrupts()
    向线程发送中断请求。线程的中断状态将被设置为 true。如果目前该线程被一个 sleep调用阻塞,那么, InterruptedException 异常被抛出。
      static boolean interrupted()
    测试当前线程(即正在执行这一命令的线程)是否被中断。注意,这是一个静态方法。这一调用会产生副作用—它将当前线程的中断状态重置为 false。
      boolean islnterrupted()
    测试线程是否被终止。不像静态的中断方法,这一调用不改变线程的中断状态。
      static Thread currentThread()
    返回代表当前执行线程的 Thread 对象
    14.3 线程状态

    线程可以有如下 6 种状态:

    • New (新创建)
    • Runnable (可运行)
    • Blocked (被阻塞)
    • Waiting (等待)
    • Timed waiting (计时等待)
    • Terminated (被终止)

    要确定一个线程的当前状态, 可调用 getState 方法。

    14.3.1 新创建线程

    当用 new 操作符创建一个新线程时, 如 newThread®, 该线程还没有开始运行。这意味着它的状态是 new。当一个线程处于新创建状态时, 程序还没有开始运行线程中的代码。在线程运行之前还有一些基础工作要做。

    14.3.2 可运行线程

    一旦调用 start 方法,线程处于 runnable 状态。

    现在所有的桌面以及服务器操作系统都使用抢占式调度。但是,像手机这样的小型设备可能使用协作式调度。

    记住,在任何给定时刻,二个可运行的线程可能正在运行也可能没有运行(这就是为什么将这个状态称为可运行而不是运行。

    14.3.3 被阻塞线程和等待线程

    当线程处于被阻塞或等待状态时,它暂时不活动。它不运行任何代码且消耗最少的资源。直到线程调度器重新激活它。 细节取决于它是怎样达到非活动状态的。

      当一个线程试图获取一个内部的对象锁(而不是 javiutiUoncurrent 库中的锁,) 而该锁被其他线程持有, 则该线程进人阻塞状态 。当所有其他线程释放该锁,并且线程调度器允许本线程持有它的时候,该线程将变成非阻塞状态
      当线程等待另一个线程通知调度器一个条件时, 它自己进入等待状态
    有几个方法有一个超时参数。调用它们导致线程进人计时等待(timed waiting) 状态。这一状态将一直保持到超时期满或者接收到适当的通知

    14.3.4 被终止的线程

    线程因如下两个原因之一而被终止:
      因为 run 方法正常退出而自然死亡。
      因为一个没有捕获的异常终止了 run 方法而意外死亡
    特别是, 可以调用线程的 stop 方法杀死一个线程。 该方法抛出 ThreadDeath 错误对象 ,由此杀死线程。但是,stop 方法已过时, 不要在自己的代码中调用这个方法。
    【API】java.iang.Thread 1.0:
      void join( )
    等待终止指定的线程。
      void join( long millis )
    等待指定的线程死亡或者经过指定的毫秒数。
      Thread.State getState () 5 . 0
    得到这一线程的状态;NEW、RUNNABLE BLOCKED、 WAITING 、TIMED_WAITNG或 TERMINATED 之一。
      void stop( )
    停止该线程。这一方法已过时
      void suspend()
    暂停这一线程的执行。这一方法已过时。
      void resume()
    恢复线程。这一方法仅仅在调用 suspend() 之后调用。这一方法已过时

    第二部分:实验部分

    实验1: 导入第13示例程序,测试程序并进行代码注释。

    测试程序1

    elipse IDE中调试运行教材585页程序13-1,结合程序运行结果理解程序;

    将所生成的JAR文件移到另外一个不同的目录中,再运行该归档文件,以便确认程序是从JAR文件中,而不是从当前目录中读取的资源。

    掌握创建JAR文件的方法;

    package resource;
    
    import java.awt.*;
    import java.io.*;
    import java.net.*;
    import java.util.*;
    import javax.swing.*;
    
    /**
     * @version 1.41 2015-06-12
     * @author Cay Horstmann
     */
    public class ResourceTest
    {
       public static void main(String[] args)
       {
          EventQueue.invokeLater(() -> {
             JFrame frame = new ResourceTestFrame();
             frame.setTitle("ResourceTest");//设置标题
             frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//关闭界面的操作
             frame.setVisible(true);//设置可见性
          });
       }
    }
    
    /**
      * 一个加载图像和文本资源的框架
     */
    class ResourceTestFrame extends JFrame
    {
    	//定义像素长和宽
       private static final int DEFAULT_WIDTH = 300;
       private static final int DEFAULT_HEIGHT = 300;
    
       public ResourceTestFrame()//定义ResourceTestFrame类
       {
          setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT);
          //获取资源文件
          URL aboutURL = getClass().getResource("about.gif");
          Image img = new ImageIcon(aboutURL).getImage();
        //在找到ResourceTest类的地方查找about.gif图像文件
          setIconImage(img);
    
          JTextArea textArea = new JTextArea();
        //读取about.txt文件
          InputStream stream = getClass().getResourceAsStream("about.txt");
          try (Scanner in = new Scanner(stream, "UTF-8"))
          {
             while (in.hasNext())
                textArea.append(in.nextLine() + "
    ");
          }//捕获异常
          add(textArea);
       }
    }
    

    运行结果:

     将所生成的JAR文件移到另外一个不同的目录中,再运行该归档文件:

     

      

     

    然后我也不知道要怎么处理进行下一步了……

    测试程序2

    elipse IDE中调试运行ThreadTest,结合程序运行结果理解程序;

    掌握线程概念;

    掌握用Thread的扩展类实现线程的方法;

    利用Runnable接口改造程序,掌握用Runnable接口创建线程的方法。

    package ThreadTest;
    
    class Lefthand extends Thread { 
    	   public void run()
    	   {
    	       for(int i=0;i<=5;i++)
    	       {  System.out.println("You are Students!");
    	           try{   sleep(500);   }// 休眠时间为500毫秒
    	           catch(InterruptedException e)// 阻塞状态
    	           { System.out.println("Lefthand error.");}    
    	       } 
    	  } 
    	}
    	class Righthand extends Thread {
    	    public void run()
    	    {
    	         for(int i=0;i<=5;i++)
    	         {   System.out.println("I am a Teacher!");
    	             try{  sleep(300);  }// 休眠时间为300毫秒
    	             catch(InterruptedException e)
    	             { System.out.println("Righthand error.");}
    	         }
    	    }
    	}
    	public class ThreadTest 
    	{
    	     static Lefthand left;
    	     static Righthand right;
    	     public static void main(String[] args)
    	     {     left=new Lefthand();
    	           right=new Righthand();
    	           left.start();
    	           right.start();
    	     }
    	}

    运行结果:

    测试程序3

    Elipse环境下调试教材625页程序14-114-2 14-3,结合程序运行结果理解程序;

    Elipse环境下调试教材631页程序14-4,结合程序运行结果理解程序;

    对比两个程序,理解线程的概念和用途;

    掌握线程创建的两种技术。

    程序14-1

    package bounce;
    
    import java.awt.*;
    import java.awt.event.*;
    import javax.swing.*;
    
    /**
      * 显示一个动画弹球。
     * @version 1.34 2015-06-21
     * @author Cay Horstmann
     */
    public class Bounce
    {
       public static void main(String[] args)
       {
          EventQueue.invokeLater(() -> {
             JFrame frame = new BounceFrame();
             frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
             frame.setVisible(true);
          });
       }
    }
    
    /**
     * 框架与球组件和按钮。
     */
    class BounceFrame extends JFrame
    {
       private BallComponent comp;
       public static final int STEPS = 1000;
       public static final int DELAY = 3;
    
       /**
        * Constructs the frame with the component for showing the bouncing ball and
        * Start and Close buttons
        */
       public BounceFrame()
       {
          setTitle("Bounce");
          comp = new BallComponent();
          add(comp, BorderLayout.CENTER);
          JPanel buttonPanel = new JPanel();
          addButton(buttonPanel, "Start", event -> addBall());
          addButton(buttonPanel, "Close", event -> System.exit(0));
          add(buttonPanel, BorderLayout.SOUTH);//将buttonPanel组件整体放在南端
          pack();
       }
    
       /**
           * 将按钮添加到容器中。
        * @param c the container
        * @param title the button title
        * @param listener the action listener for the button
        */
       public void addButton(Container c, String title, ActionListener listener)
       {
          JButton button = new JButton(title);
          c.add(button);
          button.addActionListener(listener);
       }
    
       /**
            * 添加一个弹跳球到面板,使它弹跳1000次。
        */
       public void addBall()
       {
          try
          {
             Ball ball = new Ball();
             comp.add(ball);
    
             for (int i = 1; i <= STEPS; i++)
             {
                ball.move(comp.getBounds());//调用move方法
                comp.paint(comp.getGraphics());
                Thread.sleep(DELAY);//调用线程的sleep方法
             }
          }
          catch (InterruptedException e)
          {
          }
       }
    }

    程序14-2:

    package bounce;
    
    import java.awt.geom.*;
    
    /**
      *在矩形的边缘上移动和弹回的球
     * @version 1.33 2007-05-17
     * @author Cay Horstmann
     */
    public class Ball
    {
       private static final int XSIZE = 15;
       private static final int YSIZE = 15;
       private double x = 0;
       private double y = 0;
       private double dx = 1;
       private double dy = 1;
    
       /**
           * 将球移动到下一个位置,如果它击中其中一条边,则反向移动
        */
     //判断球的边界所处状态的四个条件
       public void move(Rectangle2D bounds)
       {
          x += dx;
          y += dy;
          if (x < bounds.getMinX())
          {
             x = bounds.getMinX();
             dx = -dx;
          }
          if (x + XSIZE >= bounds.getMaxX())
          {
             x = bounds.getMaxX() - XSIZE;
             dx = -dx;
          }
          if (y < bounds.getMinY())
          {
             y = bounds.getMinY();
             dy = -dy;
          }
          if (y + YSIZE >= bounds.getMaxY())
          {
             y = bounds.getMaxY() - YSIZE;
             dy = -dy;
          }
       }
    
       /**
            * 获取当前位置的球的形状。
        */
       public Ellipse2D getShape()
       {
          return new Ellipse2D.Double(x, y, XSIZE, YSIZE);
       }
    }

    程序14-3:

    package bounce;
    
    import java.awt.*;
    import java.util.*;
    import javax.swing.*;
    
    /**
      * 绘制球的组件。
     * @version 1.34 2012-01-26
     * @author Cay Horstmann
     */
    public class BallComponent extends JPanel
    {
       private static final int DEFAULT_WIDTH = 450;
       private static final int DEFAULT_HEIGHT = 350;
    
       private java.util.List<Ball> balls = new ArrayList<>();
    
       /**
           * 向组件添加一个球。
        * @param b the ball to add
        */
       public void add(Ball b)
       {
          balls.add(b);
       }
    
       public void paintComponent(Graphics g)
       {
          super.paintComponent(g); // erase background
          Graphics2D g2 = (Graphics2D) g;
          for (Ball b : balls)
          {
             g2.fill(b.getShape());
          }
       }
       
       public Dimension getPreferredSize() { return new Dimension(DEFAULT_WIDTH, DEFAULT_HEIGHT); }
    }

    运行结果:

    程序14-4:

    package bounceThread;
    
    import java.awt.*;
    import java.awt.event.*;
    
    import javax.swing.*;
    
    /**
     * Shows animated bouncing balls.
     * @version 1.34 2015-06-21
     * @author Cay Horstmann
     */
    public class BounceThread
    {
       public static void main(String[] args)
       {
          EventQueue.invokeLater(() -> {
             JFrame frame = new BounceFrame();
             frame.setTitle("BounceThread");
             frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
             frame.setVisible(true);
          });
       }
    }
    
    /**
     * The frame with panel and buttons.
     */
    class BounceFrame extends JFrame
    {
       private BallComponent comp;
       public static final int STEPS = 1000;
       public static final int DELAY = 5;
    
    
       /**
        * Constructs the frame with the component for showing the bouncing ball and
        * Start and Close buttons
        */
       public BounceFrame()
       {
          comp = new BallComponent();
          add(comp, BorderLayout.CENTER);
          JPanel buttonPanel = new JPanel();
          addButton(buttonPanel, "Start", event -> addBall());
          addButton(buttonPanel, "Close", event -> System.exit(0));
          add(buttonPanel, BorderLayout.SOUTH);
          pack();
       }
    
       /**
        * Adds a button to a container.
        * @param c the container
        * @param title the button title
        * @param listener the action listener for the button
        */
       public void addButton(Container c, String title, ActionListener listener)
       {
          JButton button = new JButton(title);
          c.add(button);
          button.addActionListener(listener);
       }
    
       /**
        * Adds a bouncing ball to the canvas and starts a thread to make it bounce
        */
       public void addBall()
       {
          Ball ball = new Ball();
          comp.add(ball);
        //引用实现了Runnable的方法
          Runnable r = () -> { 
             try
             {  
                for (int i = 1; i <= STEPS; i++)
                {
                   ball.move(comp.getBounds());
                   comp.repaint();
                   Thread.sleep(DELAY);
                }
             }
             catch (InterruptedException e)//捕获异常
             {
             }
          };
          Thread t = new Thread(r);//用Runnable创建一个Thread对象
          t.start();//启动线程
       }
    }
    
    package bounceThread;
    
    import java.awt.*;
    import java.util.*;
    import javax.swing.*;
    
    /**
     * The component that draws the balls.
     * @version 1.34 2012-01-26
     * @author Cay Horstmann
     */
    public class BallComponent extends JComponent
    {
       private static final int DEFAULT_WIDTH = 450;
       private static final int DEFAULT_HEIGHT = 350;
    
       private java.util.List<Ball> balls = new ArrayList<>();
    
       /**
        * Add a ball to the panel.
        * @param b the ball to add
        */
       public void add(Ball b)
       {
          balls.add(b);
       }
    
       public void paintComponent(Graphics g)
       {
          Graphics2D g2 = (Graphics2D) g;
          for (Ball b : balls)
          {
             g2.fill(b.getShape());
          }
       }
       
       public Dimension getPreferredSize() { return new Dimension(DEFAULT_WIDTH, DEFAULT_HEIGHT); }
    }
    
    package bounceThread;
    
    import java.awt.geom.*;
    
    /**
       A ball that moves and bounces off the edges of a 
       rectangle
     * @version 1.33 2007-05-17
     * @author Cay Horstmann
    */
    public class Ball
    {
       private static final int XSIZE = 15;
       private static final int YSIZE = 15;
       private double x = 0;
       private double y = 0;
       private double dx = 1;
       private double dy = 1;
    
       /**
          Moves the ball to the next position, reversing direction
          if it hits one of the edges
       */
       public void move(Rectangle2D bounds)
       {
          x += dx;
          y += dy;
          if (x < bounds.getMinX())
          { 
             x = bounds.getMinX();
             dx = -dx;
          }
          if (x + XSIZE >= bounds.getMaxX())
          {
             x = bounds.getMaxX() - XSIZE; 
             dx = -dx; 
          }
          if (y < bounds.getMinY())
          {
             y = bounds.getMinY(); 
             dy = -dy;
          }
          if (y + YSIZE >= bounds.getMaxY())
          {
             y = bounds.getMaxY() - YSIZE;
             dy = -dy; 
          }
       }
    
       /**
          Gets the shape of the ball at its current position.
       */
       public Ellipse2D getShape()
       {
          return new Ellipse2D.Double(x, y, XSIZE, YSIZE);
       }
    }
    

    运行结果:

    两个实验对比:第一个程序非线程的,执行一次程序要等执行完才能执行下一次;第二个程序是线程的,执行第一次程序不用等执行完可以接着执行第二次操作。

    实验总结:

        本周学习了Java应用程序的打包操作,有些地方还不太理解来…;我初步了解学习了关于线程的知识,并初步掌握了线程创建的两种方法。1)用Thread类的子类创建线程(2)用Runnable()接口实现线程;理解和掌握了线程的优先级属性及调度方法,学到了线程的七种状态。

  • 相关阅读:
    096实战 在windows下新建maven项目
    095实战 ETL的数据来源,处理,保存
    094实战 关于js SDK的程序,java SDK的程序
    093实战 Nginx日志切割,以及脚本上传nginx的切割日志
    092实战 数据收集(各种事件)
    091实战 Nginx配置(日志服务器中关于日志的产生)
    android64位机子兼容32位.so库文件
    给 Android 初学者的 Gradle 知识普及
    Android重力感应开发
    随笔之Android平台上的进程调度探讨
  • 原文地址:https://www.cnblogs.com/LZ-728672/p/12041139.html
Copyright © 2011-2022 走看看