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

    201871010105-曹玉中《面向对象程序设计(java)》第十六周学习总结

    项目 内容
    这个作业属于哪个过程 https://www.cnblogs.com/nwnu-daizh/
    这个作业的要求在哪里 https://www.cnblogs.com/zyja/p/11963340.html
    作业学习目标

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

    (2) 掌握线程概念;

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

    第一部分:理论知识。

    进程:指一个内存中运行的应用程序。例如运行QQ那么它就是一个进程,而且一个应用程序可以同时运行多个进程

    线程:线程是进程中的一个执行单元,就比如用360我们可以让它一边杀毒一边清理垃圾,那么360它就是一个进程,那么杀毒和清理垃圾就是进程下的两个线程
    注:一个程序运行后至少有一个进程,一个进程中可以包含多个线程

    Thread类
    构造方法:
    public Thread() :分配一个新的线程对象。

    public Thread(String name) :分配一个指定名字的新的线程对象。

    public Thread(Runnable target) :分配一个带有指定目标新的线程对象。

    public Thread(Runnable target,String name) :分配一个带有指定目标新的线程对象并指定名字。

    常用方法:
    public String getName() :获取当前线程名称。

    public void start() :导致此线程开始执行; Java虚拟机调用此线程的run方法。

    public void run() :此线程要执行的任务在此处定义代码。

    public static void sleep(long millis) :使当前正在执行的线程以指定的毫秒数暂停

    public static Thread currentThread() :返回对当前正在执行的线程对象的引用。

    创建线程的方式总共有两种:
    1.是继承Thread类方式
    2.是实现Runnable接口

    创建线程的方式一:

    定义Thread类子类,并重写该类的run()方法,run()方法的方法体就代表了线程需要完成的任务,
    创建Thread子类的实例3. 调用Thread的start()方法来启动该线程
    代码如下:

    public class Test {
    public static void main(String[] args) {
    MyThread mt = new MyThread();
    Thread t1 = new Thread(mt);    
    t1.start();    
    }
    }
    class MyThread extends Thread{
    @Override
    public void run(){
    System.out.println("第一种方式创建线程");    
    }
    }

    创建线程的方式二:

    定义Runnable接口的实现类,并重写该接口的run()方法,run()方法的方法体代表线程完成的任务
    创建Runnable实现类的实例。
    调用Thread的start()方法来启动线程。
    代码如下:

    public class Test {
    public static void main(String[] args) {
    MyRunnable mr = new MyRunnable();
    Thread t1 = new Thread(mr);
    t1.start();
    }
    }
    class MyRunnable implements Runnable{
    @Override
    public void run(){
    System.out.println("第二种方式创建线程");    
    }
    }

    Thread和Runnable的区别
    因为类都是单继承的,如果一个类继承Thread,就不可以继承其他类了。但是如果实现了Runnable接口的话,则很容易的实现资源共享,避免了java中的单继承的局限性,所以Runnable比Thread更有优势

    用匿名内部类创建线程
    使用匿名内部类的方式实现Runnable接口,重写Runnable接口中的run方法:

    代码如下:

    public class Test {
    public static void main(String[] args) {
    new Thread(new Runnable(){
    @Override
    public void run() {
    System.out.println("匿名内部类创建线程");
    }
    }).start();
    }
    }

    线程安全问题的概述
    如果有多个线程在同时运行,而这些线程可能会同时运行这段代码。程序每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的,就是线程安全的。
    那么什么是线程不安全的呢?我们由一段代码看一下:
    这里我想打印的是1-100之间的整数:

    public class Test {
    public static void main(String[] args) {
    MyRunnable r = new MyRunnable();
    Thread t1 = new Thread(r);
    Thread t2 = new Thread(r);
    Thread t3 = new Thread(r);
    t1.start();
    t2.start();
    t3.start(); 
    }
    }
    class MyRunnable implements Runnable{
    private int sum = 100;
    public void run(){
    while(true){
    if(sum>0){
    try {
    Thread.sleep(10);
    catch (InterruptedException e) {
    e.printStackTrace();
    }
    System.out.println(sum);
    sum--;
    }
    }
    }
    }

    运行结果出现了很多重复的,甚至还有-1,结果和预期是不一样的,这就是线程不安全情况。那么为什么会出现这种情况呢?是因为这三个线程在执行过程中不断抢夺CPU的执行权,当某一个线程运行到Thread.sleep(10)的时候处于睡眠状态,那么CPU的执行权交给了另外两个线程以此类推,三个线程都执行到了这里,这时代码就不是一条判断一条输出了,当睡眠结束后三条线程面临的都是一条输出语句一个sum–不再判断sum的值,若最后判断sum的值为1,最后sum的值将被–三次,所以才会导致最终的结果出现0和-1的情况(最终sum的值为-2),这里的Thread.sleep()其实是为了增加线程安全问题出现的概率。
    第二部分:实验。

    测试程序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);
          });
       }
    }
    
    /**
     * 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");
          Image img = new ImageIcon(aboutURL).getImage();
          setIconImage(img);
    
          JTextArea textArea = new JTextArea();
          InputStream stream = getClass().getResourceAsStream("about.txt");
          try (Scanner in = new Scanner(stream, "UTF-8"))
          {
             while (in.hasNext())
                textArea.append(in.nextLine() + "
    ");
          }
          add(textArea);
       }
    }
    Main-Class: resource.ResourceTest

    Core Java: Fundamentals
    10th Edition
    Cay Horstmann and Gary Cornell
    Copyright 漏 2016
    Prentice-Hall

     

     

    运行结果如下:

     

     

     

    测试程序2:

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

    l 掌握线程概念;

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

    l 利用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();
         }
    }

     

    运行结果如下:

     

     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);
                } 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);
                } catch (InterruptedException e) {
                    System.out.println("Righthand error.");
                }
            }
        }
    }
    
    public class ThreadTest {
        public static void main(String[] args) {
            Runnable left = new Lefthand();
            Thread a = new Thread(left);
            Runnable right = new Righthand();
            Thread b = new Thread(right);
            a.start();
            b.start();
        }
    }

    运行结果如下:

     

     

    测试程序3:

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

    代码如下:

    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);
       }
    }
    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);
       }
    }
    package bounce;
    
    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());//将按钮放入buttonPanel
          addButton(buttonPanel, "Close", event -> System.exit(0));
          add(buttonPanel, BorderLayout.SOUTH);//将buttonPanel放入边界管理器的南端
          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)//中断异常
          {
          }
       }
    }
    
    Bounce
    
    Bounce

     

     

    运行结果如下:

     

     

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

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

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

    代码如下:

    package bounceThread;
    
    import java.awt.*;
    import java.awt.event.*;
    
    import javax.swing.*;
    
    /**
     * 显示动画弹跳球
     * @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;
    
        /**
         * 用显示弹跳球以及开始和关闭按钮的组件构建框架
         */
        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();
        }
    
        /**
         * 向容器添加按钮
         * 
         * @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);
        }
    
        /**
         * 在画布上添加一个弹跳球,并启动一个线程使其弹跳
         */
        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();
        }
    }

     

    运行结果如下:

     

     

    第三部分:学习总结

       通过本章的学习,掌握了一些关于线程的相关知识,在学习的时候学的一片混乱,好在课下通过看书

    和在Mooc上 看翁凯老师的课才对本章内容有了一定的了解,但还需要再做一些练习才能够掌握本章内容

    的精髓,在做验证性实验部分内容的时候,并没有遇到很多困难,同时体验到了本章实验内容的重要性,

    但实验课的时候遇到较多问题,好在在助教学长的帮助下得以解决,我也会在课下多多学习,加强巩固

    基础知识。

  • 相关阅读:
    MATLAB 模板匹配
    ACDSee15 教你如何轻松在图片上画圈圈、画箭头、写注释
    Qt 显示一个窗体,show()函数和exec()函数有什么区别?
    Qt 将窗体变为顶层窗体(activateWindow(); 和 raise() )
    Qt QSS样式化 菜单Qmenu&QAction
    Qt 获取文件夹中的文件夹名字
    Qt 删除文件夹或者文件
    欧洲终于承认“工业4.0”失败,互联网经济严重落后中美
    深入浅出数据结构
    浅谈城市大脑与智慧城市发展趋势
  • 原文地址:https://www.cnblogs.com/nwnucyz/p/12034371.html
Copyright © 2011-2022 走看看