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

                                                                           201871010104-陈园园《面向对象程序设计(java)》第十六周学习总结

    项目 内容
    这个作业属于哪个课程 https://www.cnblogs.com/nwnu-daizh/
    这个作业要求在哪里 https://www.cnblogs.com/lily-2018/p/11441372.html
    作业学习目标

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

    (2) 掌握线程概念;

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

    第一部分:总结理论知识

                        线程的组成

                        线程ID:线程标识符。

      • 当前指令指针(PC):指向要执行的指令。

        寄存器集合:存储单元寄存器的集合。

        堆栈:暂时存放数据和地址,一般用来保护断点和现场。

        线程与进程区别

        线程和进程之间的区别,我觉得可以用这个例子来看出两者的不同,进程就是一栋房子,房子住着 3 个人,线程就是住在房子里的人。进程是一个独立的个体,有自己的资源,线程是在进程里的,多个线程共享着进程的资源。

        线程状态

        我们看到 Java 源代码里面,线程状态的枚举有如下 6 个。

        public enum State {
        
         //新建状态
         NEW,
        
         //运行状态
         RUNNABLE,
        
         //阻塞状态
         BLOCKED,
        
         //等待状态
         WAITING,
        
         //等待状态(区别在于这个有等待的时间)
         TIMED_WAITING,
        
         //终止状态
         TERMINATED;
        }
        

        下面给这 6 个状态一一做下解释。

        NEW:新建状态。在创建完 Thread ,还没执行 start() 之前,线程的状态一直是 NEW。可以说这个时候还没有真正的一个线程映射着,只是一个对象。

        RUNNABLE:运行状态。线程对象调用 start() 之后,就进入 RUNNABLE 状态,该状态说明在 JVM 中有一个真实的线程存在。

        BLOCKED:阻塞状态。线程在等待锁的释放,也就是等待获取 monitor 锁。

        WAITING:等待状态。线程在这个状态的时候,不会被分配 CPU,而且需要被显示地唤醒,否则会一直等待下去。

        TIMED_WAITING:超时等待状态。这个状态的线程也一样不会被分配 CPU,但是它不会无限等待下去,有时间限制,时间一到就停止等待。

        TERMINATED:终止状态。线程执行完成结束,但不代表这个对象已经没有了,对象可能还是存在的,只是线程不存在了。

        线程既然有这么多个状态,那肯定就有状态机,也就是在什么情况下 A 状态会变成 B 状态。下面就来简单描述一下。

        结合下图,我们 new 出线程类的时候,就是 NEW 状态,调用 start() 方法,就进入了 RUNNABLE 状态,这时如果触发等待,则进入了 WAITING 状态,如果触发超时等待,则进入 TIMED_WAITING 状态,当访问需要同步的资源时,则只有一个线程能访问,其他线程就进入 BLOCKED 状态,当线程执行完后,进入 TERMINATED 状态。

        线程的组成

        线程ID:线程标识符。

        当前指令指针(PC):指向要执行的指令。

        寄存器集合:存储单元寄存器的集合。

        堆栈:暂时存放数据和地址,一般用来保护断点和现场。

        线程与进程区别

        线程和进程之间的区别,我觉得可以用这个例子来看出两者的不同,进程就是一栋房子,房子住着 3 个人,线程就是住在房子里的人。进程是一个独立的个体,有自己的资源,线程是在进程里的,多个线程共享着进程的资源。

        线程状态

        我们看到 Java 源代码里面,线程状态的枚举有如下 6 个。

        public enum State {
        
         //新建状态
         NEW,
        
         //运行状态
         RUNNABLE,
        
         //阻塞状态
         BLOCKED,
        
         //等待状态
         WAITING,
        
         //等待状态(区别在于这个有等待的时间)
         TIMED_WAITING,
        
         //终止状态
         TERMINATED;
        }
        

        下面给这 6 个状态一一做下解释。

        NEW:新建状态。在创建完 Thread ,还没执行 start() 之前,线程的状态一直是 NEW。可以说这个时候还没有真正的一个线程映射着,只是一个对象。

        RUNNABLE:运行状态。线程对象调用 start() 之后,就进入 RUNNABLE 状态,该状态说明在 JVM 中有一个真实的线程存在。

        BLOCKED:阻塞状态。线程在等待锁的释放,也就是等待获取 monitor 锁。

        WAITING:等待状态。线程在这个状态的时候,不会被分配 CPU,而且需要被显示地唤醒,否则会一直等待下去。

        TIMED_WAITING:超时等待状态。这个状态的线程也一样不会被分配 CPU,但是它不会无限等待下去,有时间限制,时间一到就停止等待。

        TERMINATED:终止状态。线程执行完成结束,但不代表这个对象已经没有了,对象可能还是存在的,只是线程不存在了。

        线程既然有这么多个状态,那肯定就有状态机,也就是在什么情况下 A 状态会变成 B 状态。下面就来简单描述一下。

        结合下图,我们 new 出线程类的时候,就是 NEW 状态,调用 start() 方法,就进入了 RUNNABLE 状态,这时如果触发等待,则进入了 WAITING 状态,如果触发超时等待,则进入 TIMED_WAITING 状态,当访问需要同步的资源时,则只有一个线程能访问,其他线程就进入 BLOCKED 状态,当线程执行完后,进入 TERMINATED 状态。 

     Java 中如何创建一个线程

    继承 Thread 类,重写 run() 方法。

    class MyThread extends Thread {
    
        @Override
        public void run() {
            System.out.println("MyThread");
        }
    
    }

    实现 Runnable 接口,实现 run() 方法。

    class MyRunnable implements Runnable {
    
        public void run() {
            System.out.println("MyRunnable");
        }
    
    }
    

      这 2 种线程的启动方式也不一样。MyThread 是一个线程类,所以可以直接 new 出一个对象出来,接着调用 start() 方法来启动线程;而 MyRunnable 只是一个普通的类,需要 new 出线程基类 Thread 对象,将 MyRunnable 对象传进去。

    线程在Running的过程中可能会遇到阻塞(Blocked)情况:

    • 调用join()sleep()方法,sleep()时间结束或被打断,join()中断,IO完成都会回到Runnable状态,等待JVM的调度。
    • 调用wait(),使该线程处于等待池(wait blocked pool),直到notify()/notifyAll(),线程被唤醒被放到锁定池(lock blocked pool ),释放同步锁使线程回到可运行状态(Runnable)
    • 对Running状态的线程加同步锁(Synchronized)使其进入(lock blocked pool ),同步锁被释放进入可运行状态(Runnable)。

    1.实现Runnable接口,重载run(),无返回值,Runnable接口的存在主要是为了解决Java中不允许多继承的问题。

    2.继承Thread类,重写run(),通过调用Thread的start()会调用创建线程的run(),不同线程的run方法里面的代码交替执行。但由于Java不支持多继承.因此继承Thread类就代表这个子类不能继承其他类.

      • 同步:synchronized,同步的概念就是共享,只需要针对共享的资源,才需要考虑同步。

     线程同步,是指线程之间所具有的一种制约关系,一个线程的执行依赖另一个线程的消息,当它没有得到另一个线程的消息时应等待,直到消息到达时才被唤醒。

    线程中断机制是一种协作机制,也就是说通过中断并不能直接终止另一个线程,而需要被中断的线程自己处理。

    三个中断方法:

    1、interrupt()

    2、isInterrupted():方法唯一的作用只是测试线程是否已经中断。

    3、interrupted():方法的作用是测试当前线程是否已经中断,线程的中断标识位由该方法清除。

    线程终止:

    1、使用 volatile 关键字修饰 变量的方式终止

    2、使用 interrupt() 方式终止

    3、Stop 方法终止

    可以直接使用thread.stop()来强行终止线程,但是stop方法是很危险的,就象突然关闭计算机电源,而不是按正常程序关机一样,可能会产生不可预料的结果。

    线程处于阻塞状态
    线程处于阻塞状态,如使用了sleep,同步锁的wait,socket中的receiver,accept等方法时,会使线程处于阻塞状态。当调用线程的interrupt()方法时,会抛出InterruptException异常。阻塞中的那个方法抛出这个异常,通过代码捕获该异常,然后break跳出循环状态,从而让我们有机会结束这个线程的执行。

    第二部分:实验测试

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

    测试程序1

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

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

    掌握创建JAR文件的方法;

    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);
          });
       }
    }
    
    /**
     * A frame that loads image and text resources.
     */
    class ResourceTestFrame extends JFrame
    {
       private static final int DEFAULT_WIDTH = 300;
       private static final int DEFAULT_HEIGHT = 300;//定义窗口宽和高
    
       public ResourceTestFrame()//构造器
       {
          setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT);
          URL aboutURL = getClass().getResource("about.gif");//URL来指向about.gif资源地址
          Image img = new ImageIcon(aboutURL).getImage();//利用about.gif图像文件制作图标,在找到ResourceTest类的地方查找about.gif文件
          setIconImage(img);
    
          JTextArea textArea = new JTextArea();//创建文本区
          InputStream stream = getClass().getResourceAsStream("about.txt");//读取about.txt文件
          try (Scanner in = new Scanner(stream, "UTF-8"))
          {
             while (in.hasNext())
                textArea.append(in.nextLine() + "
    ");
          }
          add(textArea);
       }
    }

    运行结果:

    测试程序2:

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

    2) 掌握线程概念;

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

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

    class Lefthand extends Thread { 
       public void run()
       {
           for(int i=0;i<=5;i++)
           {  System.out.println("You are Students!");
               try{   sleep(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);  }
                 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:

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

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

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

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

    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 JPanel
    {
       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 component.
        * @param b the ball to add
        */
       public void add(Ball b)
       {
          balls.add(b);
       }
    
       public void paintComponent(Graphics g)
       {
          super.paintComponent(g); // 擦除背景
          Graphics2D g2 = (Graphics2D) g;
          for (Ball b : balls)
          {
             g2.fill(b.getShape());
          }
       }
       
       public Dimension getPreferredSize() 
      { 
           return new Dimension(DEFAULT_WIDTH, DEFAULT_HEIGHT); }
    }
    import java.awt.*;
    import java.awt.event.*;
    import javax.swing.*;
    
    /**
     * Shows an animated bouncing ball.
     * @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);
          });
       }
    }
    
    /**
     * The frame with ball component and buttons.
     */
    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);//使用边框布局管理器使其显示在窗口下方位置
          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 panel and makes it bounce 1,000 times.
        */
       public void addBall()
       {
          try
          {
             Ball ball = new Ball();
             comp.add(ball);
    
             for (int i = 1; i <= STEPS; i++)
             {
                ball.move(comp.getBounds());
                comp.paint(comp.getGraphics());
                Thread.sleep(DELAY);
             }
          }
          catch (InterruptedException e)
          {
          }
       }
    }
    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;
    
       /**
        * 将球移动到下一个位置,如果球碰到其中一条边,则反向移动
        */
       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);
       }
    }
    

      运行结果:

    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 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);
          t.start();//调用Thread类中的start方法
       }
    }
    

      运行结果:

    实验总结:

          在上节课的基础之上,又了解了一些新的知识,学习了并发,线程的创建,中断线程,线程与进程的区别,以及多线程问题等。除了之前了解的一些基础代码之外,又学会了很多其他新的代码知识以及所表示的不同含义与用法。后一节课在老师的讲解下学习了同步。java就这样学完了,以后慢慢回顾反思。

  • 相关阅读:
    231. Power of Two
    204. Count Primes
    205. Isomorphic Strings
    203. Remove Linked List Elements
    179. Largest Number
    922. Sort Array By Parity II
    350. Intersection of Two Arrays II
    242. Valid Anagram
    164. Maximum Gap
    147. Insertion Sort List
  • 原文地址:https://www.cnblogs.com/chanyeol1127/p/12034363.html
Copyright © 2011-2022 走看看