• 201871010128-杨丽霞《面向对象程序设计(java)》第十六周学习总结


    201871010128-杨丽霞《面向对象程序设计(java)》第十六周学习总结(1分)

     

    项目

    内容

    这个作业属于哪个课程

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

    这个作业的要求在哪里

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

    作业学习目标

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

    (2) 掌握线程概念;

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

     

     

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

     14.1什么是线程

    • 进程与线程
      1,多个进程额内部数据和状态是完全独立的,而多个线程是共享一块内存空间和一组资源,有可能互相影响;
      2,每个进程都有一段专用的内存区域,而线程间可以共享相同的内存单元,(包括代码和数据)并利用这些共享单元来实现数据交换,实时通信与必要的同步操作。
    • Java实现多线程有两种途径:

      ‐创建Thread类的子类

      ‐在程序中定义实现Runnable接口的类

    • 主线程
      每个java程序都至少有一个线程,即主线程,当一个Java程序启动时,jvm会创建主线程,并在该线程中调用程序的main()方法。
      主线程的作用是:

      1.它是产生其他子线程的线程。
      2.通常它必须最后完成执行,因为它执行各种关闭动作。
      尽管主线程在程序启动时自动创建,但它可以由一个Thread对象控制。
      eg:调用Thread.currentThread()静态方法,返回调用该方法的当前线程的引用;

    Thread th1= Thread.currentThread();System.out.println("我是主线程:"+th1.getName());

     ·  创建线程的两种方法:
    1,通过实现Runnable接口,重写其中的run()方法,再调用Thread类的构造方法Thread(Runnable,Threadname)来实现
    2,通过创建Thread类的子类来实现,即继承Thread类,重写其中的run()方法
    eg:创建一个线程,可以之定义线程名字

    class HelloThread extends Thread{String name;public HelloThread(String name) {

     super(name);}

        @Overridepublic void run() {

     }}

      Java中线程的方法
    start()通过调用本线程的run()方法,使调用该方法的线程开始执行
    run() 当一个线程初始化之后,start()方法会自动的调用run()方法,在该方法内编写运行本线程时需要执行的代码,也是Runnable接口的唯一方法,一旦run()方法返回,本线程也就终止了。(一般不再线程中直接调用此方法)
    final void join() //等待该线程结束,调用了该方法的线程拥有高于其他线程的优先级
    static void yield() //把正在执行的线程临时暂停,其实就是使当前线程放弃cpu,进入就绪状态,重新排队,所以可以允许其他线程运行
    final boolean isAlive() //返回线程是否处于活动状态

    Java多线程的优点

    1. 它不会阻塞用户,因为线程是独立的,你可以同时执行多个操作,举个栗子,你需要一个延时,等待三秒钟再进行接下来的操作,如果你使用单线程,它就真的等了你三秒,这三秒,啥都不干,啥都得放一边,就等。。。这明显是不可接受的。

    2. 你可以同时执行多个操作,节省时间。这里面又牵扯到CPU密集型和IO密集型的问题

    3. 线程是独立的,死掉一个,不影响另一个。

    14.2中断线程

    JAVA中断线程三大基本方法

    方法一

    程正常执行完毕,正常结束。也就是让run方法执行完毕,该线程就会正常结束。

    方法二

    监视某些条件,结束线程的不间断运行。然而,通常有些线程是伺服线程,它们往往需要长时间的运行,只有在外部某些条件满足的情况下,才能关闭这些线程。一般情况下,它们执行在一个while(true)的死循环中。我们可以在while死循环内,每次循环时,察看外部条件,看看是否需要关闭当前线程。如果是,就break,跳出死循环,或者是抛出异常,跳出死循环,结束线程。

    方法三

    捕获InterruptedException运行时异常,中断当前线程。有些执行伺服任务的线程,在while(true)这样的死循环内部,是一个阻塞中的方法。此时,就不能采用第二种方法了。因为,当该方法没有返回时,该线程会一直处于阻塞当中,根本无法执行其他语句。这时候就需要调用该线程的interrupt方法,产生一个InterruptedException运行时异常,是阻塞中的那个方法抛出这个异常,从而让我们有机会结束这个线程的执行。一个外部的Thread 对象 指向这个线程。 需要结束这个线程时,只需要调用thread对象的interrupt() 方法,就会在responseMessage = this.getSendMessages().take();这条语句中产生一个InterruptedException异常,从而结束该线程的阻塞状态,通过抛出异常,或者break跳出死循环,结束这个线程。

    14.3 线程状态

    Java中线程的状态分为6

     1.初始(NEW):新创建了一个线程对象,但还没有调用start()方法。

    实现Runnable接口和继承Thread可以得到一个线程类,new一个实例出来,线程就进入了初始状态。

    2. 运行(RUNNABLE)Java线程中将就绪(ready)和运行中(running)两种状态统的称为“运行”。

    线程对象创建后,其他线程(比如main线程)调用了该对象的start()方法。该状态的线程位于可运行线程池中,等待被线程调度选中,获取CPU的使用权,此时处于就绪状态(ready)。就绪状态的线程在获得CPU时间片后变为运行中状态(running)。

     3.阻塞(BLOCKED):表示线程阻塞于锁。

    阻塞状态是线程阻塞在进入synchronized关键字修饰的方法或代码块(获取锁)时的状态

    4. 等待(WAITING):进入该状态的线程需要等待其他线程做出一些特定动作(通知或中断)

    处于这种状态的线程不会被分配CPU执行时间,它们要等待被显式地唤醒,否则会处于无限期等待的状态

    5. 超时等待(TIMED_WAITING):该状态不同于WAITING,它可以在指定的时间后自返回。

    处于这种状态的线程不会被分配CPU执行时间,不过无须无限期等待被其他线程显示地唤醒,在达到一定时间后它们会自动唤醒

    6.终止(TERMINATED):表示该线程已经执行完毕。

    当线程的run()方法完成时,或者主线程的main()方法完成时,我们就认为它终止了。这个线程对象也许是活的,但是,它已经不是一个单独执行的线程。线程一旦终止了,就不能复生。

    在一个终止的线程上调用start()方法,会抛出java.lang.IllegalThreadStateException异常

    第二部分:实验部分

    实验1:测试程序1(10分)

    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);
          });
       }
    }
     
    /**
     * 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
          Image img = new ImageIcon(aboutURL).getImage();//将加载的about.gif图像设置为图标
          setIconImage(img);
     
          JTextArea textArea = new JTextArea();
          InputStream stream = getClass().getResourceAsStream("about.txt");//读取about.txt文本文件内容
          try (Scanner in = new Scanner(stream, "UTF-8"))//将读取到的about.txt文本文件里内容显示到文本区
          {
             while (in.hasNext())//读取文本文件
                textArea.append(in.nextLine() + "
    ");
          }
          add(textArea);
       }
    }
    

     运行截图:

     归档截图:

     

     打开后:

    实验1:测试程序2(10分)

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

    掌握线程概念;

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

    利用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();
         }
    }
    packageThread;
    //创建Thread类的子类实现多线程
    class Lefthand extends Thread { 
           public void run()
           {
               for(int i=0;i<=5;i++)
               {  System.out.println("You are Students!");
                   try{   sleep(500);    }//给定休眠的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毫秒,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();//启动线程,调用run()方法,此方法立即返回,新线程并发运行
             }
        }

     实现Runnable之后的代码:

    package Thread
    //实现Runnable接口的类实现多线程
    class Lefthand implements Runnable{
       public void run()
       {
           
           for(int i=0;i<=5;i++)
           {  System.out.println("You are Students!");
               try{ Thread.sleep(500);   }//500毫秒打印一次
               catch(InterruptedException e)//中断异常
               { System.out.println("Lefthand error.");}    
           } 
      } 
    }
    class Righthand implements Runnable {
        public void run()
        {
            for(int i=0;i<=5;i++)
             {   System.out.println("I am a Teacher!");
                 try{  Thread.sleep(300);  }//300毫秒打印一次
                 catch(InterruptedException e)
                 { System.out.println("Righthand error.");}
             }
        }
    }
    public class ThreadTest 
    {
         static Thread left;
         static Thread right;
         public static void main(String[] args)
         {    
               Runnable lefthand = new Lefthand();
               left=new Thread(lefthand);
               left.start();
               Runnable righthand = new Righthand();
               right=new Thread(righthand);
               right.start();
                   
         }
    }
     

    运行截图:

     实验1:测试程序3(10分)

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

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

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

    掌握线程创建的两种技术

    程序14-1、14-2 14-3如下:

    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;
     
       /**
        * 创建面板容器显示滚动的小球和两个按钮
        */
       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();
       }
     
       /**
        * 添加按钮
        * @param 容器c
        * @param 按钮标题
        * @param 按钮动作相应
        */
       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());//小球每一次移动的尺寸
                comp.paint(comp.getGraphics());
                Thread.sleep(DELAY);//3毫秒移动一次 
              }
             } 
    catch (InterruptedException e)
    
     {
     } 
    }
     }
    package bounce;
     
    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<>();
     
       /**
        * 在容器上添加一个球
        * @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); }
    }
    package bounce;
     
    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;
          }
       }
     
       /**
        *在当前位置得到小球的形状 
        */<br>//定义球外形
    
    public Ellipse2D getShape() { 
       return new Ellipse2D.Double(x, y, XSIZE, YSIZE); 
    }

    运行截图:

     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);
          });
       }
    }
     
    /**
     *  框架与球组件和按钮
     */
    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();
       }
    }

    运行截图:

     实验总结:(15分)

    本周学习了线程,实现多线程,通过创建Thread类的子类,在程序中实现Runnable接口的类,创建线程的两种方法:
    通过实现Runnable接口,重写其中的run()方法,再调用Thread类的构造方法Thread(Runnable,Threadname)来实现
    通过创建Thread类的子类来实现,即继承Thread类,重写其中的run()方法
    Java 的线程调度采用优先级策略:优先级高的先执行,优先级低的后执行;多线程系统会自动为每个线程分配一个优先级,缺省时,继承其父类的优先级;任务紧急的线程,其优先级较高; 同优先级的线程按“先进先出”的队列原则。线程的六种状态,以及他们之间的状态变换,各个状态的特征,3个测试程让我们对线程有了更直观的体验。
  • 相关阅读:
    [HDU2136] Largest prime factor(素数筛)
    [luoguP1082] 同余方程(扩展欧几里得)
    基本数论算法
    [luoguP2444] [POI2000]病毒(AC自动机 + dfs)
    [luoguP2564] [SCOI2009]生日礼物(队列)
    在EditText插入表情,并发送表情
    程序员自我提高的几点建议
    CSS3悬停特效合集Hover.css
    带动画效果的jQuery手风琴
    android程序的真正入口
  • 原文地址:https://www.cnblogs.com/ylxzjh/p/12049888.html
Copyright © 2020-2023  润新知