项目

内容

这个作业属于哪个课程

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

这个作业的要求在哪里

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

作业学习目标

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

(2) 掌握线程概念;

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

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

14.1什么是线程

1.进程--概念

要解释线程,就必须明白什么是进程。

什么是进程呢?

进程是指运行中的应用程序,每个进程都有自己独立的地址空间(内存空间),比如用户点击桌面的IE浏览器,就启动了一个进程,操作系统就会为该进程分配独立的地址空间。当用户再次点击左面的IE浏览器,又启动了一个进程,操作系统将为新的进程分配新的独立的地址空间。目前操作系统都支持多进程。

要点:用户每启动一个进程,操作系统就会为该进程分配一个独立的内存空间。

2.线程--概念

在明白进程后,就比较容易理解线程的概念。

什么是线程呢?

是进程中的一个实体,是被系统独立调度和分派的基本单位,线程自己不拥有系统资源,只拥有一点在运行中必不可少的资源,但它可与同属一个进程的其它线程共享进程所拥有的全部资源。一个线程可以创建和撤消另一个线程,同一进程中的多个线程之间可以并发执行。线程有就绪、阻塞和运行三种基本状态。

3.线程

1、线程是轻量级的进程

2、线程没有独立的地址空间(内存空间)

3、线程是由进程创建的(寄生在进程)

4、一个进程可以拥有多个线程-->这就是我们常说的多线程编程

5、线程有几种状态:

a、新建状态(new)

b、就绪状态(Runnable)

c、运行状态(Running)

d、阻塞状态(Blocked)

e、死亡状态(Dead)

4.线程有什么用处

java程序中流传一句话,不会使用线程就别跟别人说自己学过java。目前绝大部分应用程序都会涉及到多并发的问题。只要应用程序涉及到并发,就离不开多线程编程。

5.线程--如何使用

在java中一个类要当作线程来使用有两种方法。

1、继承Thread类,并重写run函数

2、实现Runnable接口,并重写run函数

因为java是单继承的,在某些情况下一个类可能已经继承了某个父类,这时在用继承Thread类方法来创建线程显然不可能java设计者们提供了另外一个方式创建线程,就是通过实现Runnable接口来创建线程。

14.2中断线程

Terminated (被终止) 线程被终止的原因有二:

(1)一是run()方法中最后一个语句执行完毕而自 然死亡。

(2)二是因为一个没有捕获的异常终止了run方法 而意外死亡。

可以调用线程的stop 方 法 杀 死 一 个 线 程 (thread.stop();),但是,stop方法已过时, 不要在自己的代码中调用它。

其他判断和影响线程状态的方法:

(1)join():等待指定线程的终止。

(2)join(long millis):经过指定时间等待终止指定 的线程。

(3)isAlive():测试当前线程是否在活动。

(4)yield():让当前线程由“运行状态”进入到“就 绪状态”,从而让其它具有相同优先级的等待线程 获取执行权。

14.3线程状态

Java中线程的状态分为6种。

1. 初始(NEW):新创建了一个线程对象,但还没有调用start()方法。
2. 运行(RUNNABLE):Java线程中将就绪(ready)和运行中(running)两种状态笼统的称为“运行”。
线程对象创建后,其他线程(比如main线程)调用了该对象的start()方法。该状态的线程位于可运行线程池中,等待被线程调度选中,获取CPU的使用权,此时处于就绪状态(ready)。就绪状态的线程在获得CPU时间片后变为运行中状态(running)。
3. 阻塞(BLOCKED):表示线程阻塞于锁。
4. 等待(WAITING):进入该状态的线程需要等待其他线程做出一些特定动作(通知或中断)。
5. 超时等待(TIMED_WAITING):该状态不同于WAITING,它可以在指定的时间后自行返回。
6. 终止(TERMINATED):表示该线程已经执行完毕。

这6种状态定义在Thread类的State枚举中,可查看源码进行一一对应。

线程的状态图     

第二部分:实验部分

1、实验目的与要求

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

(2) 掌握线程概念;

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

2、实验内容和步骤

实验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()
{
setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT); //在找到ResourceTest类的地方查找about.gif文件
URL aboutURL = getClass().getResource("about.gif"); //将此图像设置为框架的图标
Image img = new ImageIcon(aboutURL).getImage();
setIconImage(img); JTextArea textArea = new JTextArea(); //getResourceAsStream方法的作用是找到与类位于同一位置的资源,返回一个可以加载资源的URL或者输入流
InputStream stream = getClass().getResourceAsStream("about.txt"); //在读取文本时使用同一编码UTF-8
try (Scanner in = new Scanner(stream, "UTF-8"))
{
while (in.hasNext())
textArea.append(in.nextLine() + "\n");
}
add(textArea);
}
}

运行截图如下:

归档截图如下:

     

打开后:

测试程序2:

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

l 掌握线程概念;

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

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

程序代码如下:

 package ThreadTest;

 class Lefthand extends Thread {
public void run()
{
for(int i=0;i<=5;i++)
{ System.out.println("You are Students!");
//调用Thread的sleep方法不会创建一个新线程,
//sleep是Thread的静态方法,用于暂停当前线程的活动
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接口改造的程序如下:

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

运行截图如下:

测试程序3:

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

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

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

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

程序代码如下:

 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);
}
}
 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
*/ //创建add方法,在add方法中使用球类型集合的add方法向集合中添加球
public void add(Ball b)
{
balls.add(b);
} //paintComponent方法中有一个Graphics类型的参数,这个参数保留着用于绘制图像和文本的设置。
//在Java中,所有的绘制都必须使用Graphics对象,其中包含了绘制图案,图像和文本的方法。
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.*;
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(); //使用addBuuton方法为按钮添加标题,监听器,并且将按钮添加至面板中
addButton(buttonPanel, "Start", event -> addBall());
addButton(buttonPanel, "Close", event -> System.exit(0)); //将按钮面板添加至框架的南部
add(buttonPanel, BorderLayout.SOUTH);
pack();
} /**
*向容器添加按钮
* @param c the container
* @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);
}
}
//中断异常
catch (InterruptedException e)
{
}
}
}

运行结果如下:

Ball类程序代码如下:

 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);
}
}

BallComponent类代码如下:

 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
*/ //创建add方法,在add方法中使用球类型集合的add方法向集合中添加球
public void add(Ball b)
{
balls.add(b);
} //paintComponent方法中有一个Graphics类型的参数,这个参数保留着用于绘制图像和文本的设置。
//在Java中,所有的绘制都必须使用Graphics对象,其中包含了绘制图案,图像和文本的方法。
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); }
}

BounceThread类代码如下:

 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 为按钮设置标题
* @param 为按钮设置监听器
*/
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); //将移动球的代码放置在一个独立的线程中,运行这段代码可以提高弹跳球的相应性能
//实现一个BallRunnable类,然后,将动画代码放在run方法中,这样就即将动画代码放在了一个单独的线程中
Runnable r = () -> {
try
{
for (int i = 1; i <= STEPS; i++)
{
ball.move(comp.getBounds());
//调用组件的repaint方法,重新绘制组件
comp.repaint();
Thread.sleep(DELAY);
}
}
catch (InterruptedException e)
{
}
}; //将Runnable对象作为入口参数传入Thread的构造函数,再调用start方法就可以启动线程
Thread t = new Thread(r);
t.start();
}
}

运行结果如下:

第三部分:实验总结

通过这次实验,我主要掌握了多线程在程序中的的实现。通过测试程序三的运行结果很直观的让我线程有了一定的认识。对本周实验由于都是测试性程序并且作业量也比较少,感觉还是比较容易完成。前几次做实验的过程中又遇到导入的程序没有错误却运行不出来这种问题,这个星期在同学的帮助下都可以运行出来了。

201871010131-张兴盼《面向对象程序设计(java)》第十六周学习总结的更多相关文章

  1. 201571030332 扎西平措 《面向对象程序设计Java》第八周学习总结

    <面向对象程序设计Java>第八周学习总结   项目 内容 这个作业属于哪个课程 https://www.cnblogs.com/nwnu-daizh/ 这个作业的要求在哪里 https: ...

  2. 201771010118马昕璐《面向对象程序设计java》第八周学习总结

    第一部分:理论知识学习部分 1.接口 在Java程序设计语言中,接口不是类,而是对类的一组需求描述,由常量和一组抽象方法组成.Java为了克服单继承的缺点,Java使用了接口,一个类可以实现一个或多个 ...

  3. 201771010134杨其菊《面向对象程序设计java》第八周学习总结

    第八周学习总结 第一部分:理论知识 一.接口.lambda和内部类:  Comparator与comparable接口: 1.comparable接口的方法是compareTo,只有一个参数:comp ...

  4. 201771010134杨其菊《面向对象程序设计java》第七周学习总结

    第七周学习总结 第一部分:理论知识 1.继承是面向对象程序设计(Object Oriented Programming-OOP)中软件重用的关键技术.继承机制使用已经定义的类作为基础建立新的类定义,新 ...

  5. 201771010128 王玉兰《面象对象程序设计 (Java) 》第六周学习总结

    ---恢复内容开始--- 第一部分:基础知识总结: 1.继承 A:用已有类来构建新类的一种机制,当定义了一个新类继承一个类时,这个新类就继承了这个类的方法和域以适应新的情况: B:特点:具有层次结构. ...

  6. 201871010126 王亚涛《面向对象程序设计 JAVA》 第十三周学习总结

      内容 这个作业属于哪个课程 https://www.cnblogs.com/nwnu-daizh/ 这个作业的要求在哪里 https://www.cnblogs.com/nwnu-daizh/p/ ...

  7. 201871010126 王亚涛 《面向对象程序设计 (Java)》第十七周学习总结

    内容 这个作业属于哪个课程 https://www.cnblogs.com/nwnu-daizh/ 这个作业的要求在哪里 https://www.cnblogs.com/nwnu-daizh/p/12 ...

  8. 马凯军201771010116《面向对象程序设计Java》第八周学习总结

    一,理论知识学习部分 6.1.1 接口概念 两种含义:一,Java接口,Java语言中存在的结构,有特定的语法和结构:二,一个类所具有的方法的特征集合,是一种逻辑上的抽象.前者叫做“Java接口”,后 ...

  9. 周强201771010141《面向对象程序设计Java》第八周学习总结

    一.理论知识学习部分 Java为了克服单继承的缺点,Java使用了接口,一个类可以实现一个或多个接口. 接口体中包含常量定义和方法定义,接口中只进行方法的声明,不提供方法的实现. 类似建立类的继承关系 ...

  10. 201777010217-金云馨《面向对象程序设计Java》第八周学习总结

    项目 内容 这个作业属于哪个课程 https://www.cnblogs.com/nwnu-daizh/ 这个作业的要求在哪里 https://www.cnblogs.com/nwnu-daizh/p ...

随机推荐

  1. [PHP] 阿里云 Composer 全量镜像

    阿里云 Composer 全量镜像 镜像地址:https://mirrors.aliyun.com/composer/

  2. 怎样用cmd脚本添加Qt的环境变量

    在网上遍历了很久,终于找到了一个简单且令人满意的答案: 定位到PyQt5发布文件所需的plugins的位置: 新建一个名为“设置环境变量”的cmd脚本,在里面写上: wmic ENVIRONMENT ...

  3. 【SpringCloud之pigx框架学习之路 】2.部署环境

    [SpringCloud之pigx框架学习之路 ]1.基础环境安装 [SpringCloud之pigx框架学习之路 ]2.部署环境 1.下载代码 git clone https://git.pig4c ...

  4. spring cloud 与spring boot 版本不匹配引发的问题总结

    为了将前期项目慢慢转移到微服务上,今天开始搭建eureka服务时,出现以下错误: org.springframework.context.ApplicationContextException: Un ...

  5. 诡异问题:tomcat启动一直卡住,strace跟踪提示apache-tomcat核心文件找不到。

    最近遇到了一个诡异的tomcat问题,被这个问题折磨了2天.是这样的,启动tomcat后一直卡在这个点上: org.apache.catalina.core.StandardEngine.startI ...

  6. POJ 1094 (传递闭包 + 拓扑排序)

    题目链接: POJ 1094 题目大意:有 1 ~ N 个大写字母,且从 A 开始依次 N 个.再给你 M 个小于的关系,比如 A < B ,让你判断三种可能: 1.在第 i 个关系罗列之后,是 ...

  7. VMware 中安装kvm虚拟机

    环境准备: 安装vmware时需要自定义安装-开启虚拟化技术   安装成功之后就可以继续进行了. 1 查看CPU是否支持KVM egrep 'vmx|svm' /proc/cpuinfo --colo ...

  8. vuex 源码分析(七) module和namespaced 详解

    当项目非常大时,如果所有的状态都集中放到一个对象中,store 对象就有可能变得相当臃肿. 为了解决这个问题,Vuex允许我们将 store 分割成模块(module).每个模块拥有自己的 state ...

  9. 使用Node.js时如何引入jQuery

    使用Node.js时如何引入jQuery 首先安装jQuery依赖 npm install jquery 然后安装jsdom npm install jsdom 引入jQuery 新版正确的依赖方式 ...

  10. Restful服务应不应该在URI中加入版本号

    程序员们对于Restful服务应不应该在URI中加入版本信息的问题在stackoverflow上进行了积极的讨论: Best practices for API versioning ,该问题被赞了7 ...