201871010123-吴丽丽 《面向对象程序设计(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知识内容

1、程序与进程的概念:

(1)程序是一段静态的代码,它是应用程序执行的蓝本。

(2)进程是程序的一次动态执行,它对应了从代码加载、执行至执行完毕的一个完整过程。

(3)操作系统为每个进程分配一段独立的内存空间和系统资源,包括:代码数据以及堆栈等资源。每 一个进程的内部数据和状态都是完全独立的。

(4)多任务操作系统中,进程切换对CPU资源消耗较大。

2、多线程的概念:

(1)多线程是进程执行过程中产生的多条执行线索。

(2)线程是比进程执行更小的单位。

(3)线程不能独立存在,必须存在于进程中,同一进程的各线程间共享进程空间的数据。

(4)每个线程有它自身的产生、存在和消亡的过程, 是一个动态的概念。

(5)多线程意味着一个程序的多行语句可以看上去几 乎在同一时间内同时运行。

(6)线程创建、销毁和切换的负荷远小于进程,又称为轻量级进程(lightweight process)。

3、Java实现多线程有两种途径:
(1)创建Thread类的子类

(2)在程序中定义实现Runnable接口的类

4、用Thread类的子类创建线程:

(1)首先需从Thread类派生出一个子类,在该子类中重写run()方法。

class hand extends Thread {
public void run() {……}
}

(2) 然后创建该子类的对象

Lefthand left=new Lefthand();
Righthand right=new Righthand();

(3)最后用start()方法启动线程

left.start();
right.start();

5、用Thread类的子类创建多线程的关键性操作:

(1)定义Thread类的子类并实现用户线程操作,即 run()方法的实现。

(2)在适当的时候启动线程。

(3)  由于Java只支持单重继承,用这种方法定义的类不可再继承其他父类。

6、用Runnable()接口实现线程

(1)首先设计一个实现Runnable接口的类;

(2) 然后在类中根据需要重写run方法;

(3)再创建该类对象,以此对象为参数建立Thread 类的对象;

(4)调用Thread类对象的start方法启动线程,将 CPU执行权转交到run方法。

例如:

class A implements Runnable{
public void run(){….}
}
class B {
public static void main(String[] arg){
Runnable a=new A();
Thread t=new Thread(a);
t.start();
}
}

7、线程的终止

(1)当线程的run方法执行方法体中最后一条语句后,或者出现了在run方法中没有捕获的异常时,线程将终止,让出CPU使用权。

(2)调用interrupt()方法也可终止线程。

-----void interrupt()

(3)向一个线程发送一个中断请求,同时把这个线程的“interrupted”状态置为true。

(4)若该线程处于 blocked 状态 ,会抛出 InterruptedException。

8、测试线程是否被中断的方法

(1)Java提供了几个用于测试线程是否被中断的方法。

-static boolean interrupted()

(2)检测当前线程是否已被中断 ,并重置状态 “interrupted”值为false。

-boolean isInterrupted()

(3)检测当前线程是否已被中断 ,不改变状态 “interrupted”值 。

9、线程的状态:

(1)利用各线程的状态变换,可以控制各个线程轮流使用CPU,体现多线程的并行性特征。

(2)线程有如下7种状态:

➢ New (新建)

➢ Runnable (可运行)

➢ Running(运行)

➢ Blocked (被阻塞)

➢ Waiting (等待)

➢ Timed waiting (计时等待)

➢ Terminated (被终止)

10、新创建线程

new(新建)

-----线程对象刚刚创建,还没有启动,此时线程还处于不可运行状态。例如: Thread thread=new Thread(r);此时线程thread处于新建状态,有了相应的内存空间以及 其它资源。

11、可运行线程

- runnable(可运行状态)

➢ 此时线程已经启动,处于线程的run()方法之中。

➢ 此时的线程可能运行,也可能不运行,只要 CPU一空闲,马上就会运行。

➢ 调用线程的start()方法可使线程处于“可运行”状态。例如: thread.start();

12、被阻塞线程和等待线程

- blocked (被阻塞)

➢ 一个正在执行的线程因特殊原因,被暂停执行, 进入阻塞状态。

➢ 阻塞时线程不能进入队列排队,必须等到引起阻塞的原因消除,才可重新进入排队队列。

➢ 引起阻塞的原因很多,不同的原因要用不同的方法解除。

-sleep(),wait()是两个常用引起线程阻塞的方法。

13、线程阻塞的三种情况:

(1)等待阻塞 :通过调用线程的wait()方法,让线程等待某工作的完成。

(2)同步阻塞 :线程在获取synchronized同步锁失 败(因为锁被其它线程所占用),它会进入同步阻 塞状态。

(3)其他阻塞 :通过调用线程的sleep()或join() 或发出了I/O请求时,线程会进入到阻塞状态。当 sleep()状态超时、join()等待线程终止或者超 时、或者I/O处理完毕时,  线程重新转入就绪状态。

14、被终止的线程

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

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

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

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

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

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

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

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

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

16、多线程调度

(1)Java提供一个线程调度器来监控程序启动后进入可运行状态的所有线程。线程调度器按照线程的优先级决定应调度哪些线程来执行。

(2)处于可运行状态的线程首先进入就绪队列排队等候处理器资源,同一时刻在就绪队列中的线程可能有多个。Java的多线程系统会给每个线程自动分配一个线程的优先级。

17、Java 的线程调度采用优先级策略:

(1)优先级高的先执行,优先级低的后执行;

(2)多线程系统会自动为每个线程分配一个优先级,缺省时,继承其父类的优先级;

(3)任务紧急的线程,其优先级较高;

(4)同优先级的线程按“先进先出”的队列原则;

18、守护线程

(1)守护线程的惟一用途是为其他线程提供服务。例如计时线程。

(2)在一个线程启动之前,调用setDaemon方法可将线程转换为守护线程(daemon thread)。 例如: setDaemon(true);

19、Thread类有三个与线程优先级有关的静态量:

➢ MAX_PRIORITY:最大优先权,值为10;

➢ MIN_PRIORITY:最小优先权,值为1;

➢ NORM _PRIORITY:默认优先权,值为5。

第二部分:实验部分

实验十四  应用程序归档与线程初步

实验时间 2019-12-12

1、实验目的与要求

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

(2) 掌握线程概念;

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

2、实验内容和步骤

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

测试程序1

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

l 将所生成的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 long serialVersionUID = 1L;
private static final int DEFAULT_WIDTH = ;
private static final int DEFAULT_HEIGHT = ; public ResourceTestFrame()
{
setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT);
URL aboutURL = getClass().getResource("about.gif"); //在getclass方法的getResourse下查找about.gif文件
System.out.println(aboutURL);
Image img = new ImageIcon(aboutURL).getImage();//利用about.gif图像文件制作图标
setIconImage(img); JTextArea textArea = new JTextArea();//创建一个textArea对象
InputStream stream = getClass().getResourceAsStream("about.txt");//读取about.txt文件
try (Scanner in = new Scanner(stream, "UTF-8"))
{
while (in.hasNext())
textArea.append(in.nextLine() + "\n");
}
add(textArea);
}
}

运行结果如下:

利用Eclipse方式导出jar文件的步骤:

选中ResourceTest---->右键,Export...---->Java---->JAR file---->next---->在JAR file的这一文本区内输入Resource.jar---->next---->next----> 选 择 Main class---->Finish.

导出的文件如下:

双击Resourse.jar之后就出现以下页面:

测试程序2:

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

l 掌握线程概念;

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

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

ThreadTest.java代码如下:

class Lefthand extends Thread {
public void run()
{
for(int i=0;i<=5;i++)
{ System.out.println("You are Students!");
try{ sleep(500); } //用了sleep()方法,休眠500毫秒
catch(InterruptedException e)
{ System.out.println("Lefthand error.");}
}
}
}
class Righthand extends Thread {
public void run() //重写run方法
{
for(int i=0;i<=5;i++)
{ System.out.println("I am a Teacher!");
try{ sleep(300); } //用了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{             //用Runnable()接口实现线程
public void run()
{ for(int i=;i<=;i++)
{ System.out.println("You are Students!");
try{ Thread.sleep(); } //调用了Thread类的start方法
catch(InterruptedException e)
{ System.out.println("Lefthand error.");}
}
}
}
class Righthand implements Runnable {
public void run()
{ for(int i=;i<=;i++)
{ System.out.println("I am a Teacher!");
try{ Thread.sleep(); }
catch(InterruptedException e)
{ System.out.println("Righthand error.");}
}
}
}
public class Thread1
{
static Lefthand left;
static Righthand right;
public static void main(String[] args)
{ //创建Runnable类型的对象,以此类对象为参数建立Thread类的对象
Runnable lefthand = new Lefthand();
Thread left=new Thread(lefthand);
left.start(); //调用left这个对象变量的start方法
Runnable righthand = new Righthand();
Thread right=new Thread(righthand);
right.start();
}
}

运行结果如下:

测试程序3:

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

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

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

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

Bounce.java代码如下:

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 = ;
public static final int DELAY = ; /**
* 使用组件构造框架,以显示弹跳球和开始和关闭按钮
*/
public BounceFrame()
{
setTitle("Bounce");
comp = new BallComponent(); //创建一个新的BallComponent类赋给comp
add(comp, BorderLayout.CENTER);
JPanel buttonPanel = new JPanel();
addButton(buttonPanel, "Start", event -> addBall());
addButton(buttonPanel, "Close", event -> System.exit());
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 = ; i <= STEPS; i++)
{
ball.move(comp.getBounds()); //调用ball这对象变量来移动球
comp.paint(comp.getGraphics()); //调用comp的paint方法来绘画
Thread.sleep(DELAY); //调用Thread类的sleep方法
}
}
catch (InterruptedException e)
{
}
}
}

BallComponent.java代码如下:

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 = ;
private static final int DEFAULT_HEIGHT = ; private java.util.List<Ball> balls = new ArrayList<>(); /**
* 向组件添加一个球。
* 要添加的球
*/
public void add(Ball b)
{
balls.add(b);
} public void paintComponent(Graphics g)
{
super.paintComponent(g); // 擦除背景
Graphics2D g2 = (Graphics2D) g;
for (Ball b : balls) //foreach循环
{
g2.fill(b.getShape()); //通过对象变量b的getShape方法来传参给fill
}
} public Dimension getPreferredSize() { return new Dimension(DEFAULT_WIDTH, DEFAULT_HEIGHT); } //通过返回一个新建Dimension类来获取组件的大小
}

Ball.java代码如下:

package bounce;

import java.awt.geom.*;

/**
* 从长方形边缘上移动和弹跳的球
* @version 1.33 2007-05-17
* @author Cay Horstmann
*/
public class Ball
{
private static final int XSIZE = ;
private static final int YSIZE = ;
private double x = ;
private double y = ;
private double dx = ;
private double dy = ; /**
* 将球移动到下一个位置,如果球碰到其中一条边,则反向移动
*/
public void move(Rectangle2D bounds)
{
x += dx;
y += dy;
if (x < bounds.getMinX()) //通过bounds来获得宽度的最小值
{
x = bounds.getMinX();
dx = -dx;
}
if (x + XSIZE >= bounds.getMaxX()) //通过bounds来获得宽度的最大值
{
x = bounds.getMaxX() - XSIZE;
dx = -dx;
}
if (y < bounds.getMinY()) //通过bounds来获得高度的最小值
{
y = bounds.getMinY();
dy = -dy;
}
if (y + YSIZE >= bounds.getMaxY()) //通过bounds来获得高度的最大值
{
y = bounds.getMaxY() - YSIZE;
dy = -dy;
}
} /**
* 获取球在当前位置的形状。
*/
public Ellipse2D getShape()
{
return new Ellipse2D.Double(x, y, XSIZE, YSIZE); //用Ellipse2D类绘制圆作为返回值
}
}

运行结果如下:

该程序的close键不可用,点击没反应

后将Bounce.java通过线程来修改,其程序为BounceThread.java来修改后,close可使用了

BounceThread.java代码如下:

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 = ;
public static final int DELAY = ; /**
* 用显示弹跳球和的组件构造框架启动和关闭按钮
*/
public BounceFrame()
{
comp = new BallComponent();
add(comp, BorderLayout.CENTER); //将comp添加到边框布局的中间
JPanel buttonPanel = new JPanel();
addButton(buttonPanel, "Start", event -> addBall());
addButton(buttonPanel, "Close", event -> System.exit());
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);
} /**
*在画布上添加一个弹跳球,并启动一根线使其弹跳
*/
public void addBall()
{
Ball ball = new Ball();
comp.add(ball); //向comp中添加球
Runnable r = () -> { //Runnable是函数式接口,用lambda表达式
try
{
for (int i = ; i <= STEPS; i++)
{
ball.move(comp.getBounds()); //将comp的getBounds方法作为参数来传递ball的move方法
comp.repaint(); //通过对象来调用repaint方法,repaint方法是在另外一个绘制线程里进行的
Thread.sleep(DELAY); //通过Thread线程来调用sleep方法
}
}
catch (InterruptedException e)
{
}
};
Thread t = new Thread(r); //创建一新的线程
t.start(); //调用start方法来启动线程
}
}

运行结果如下:

按了close按钮后就关闭程序了,该程序与前一个程序的不同是:这个体现了线程的并发性,其点一次Start就出现一个球,而前一个程序不管你点多少次start,都有等到第一个工作完之后才可运行,所以该程序很好的体现了线程的特点。

实验总结:

在本次实验中进行第一个实验时,刚刚开始不知道怎么将jar文件导出来,后通过网上查询知道了如何去导出来,在该实验中也了解到了有关线程的概念和用途,学会了线程的创建方法,理解了线程优先级属性及调度方法,同时通过测试程序三能够很好的认识到了线程的特点。

201871010123-吴丽丽 《面向对象程序设计(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. 马凯军201771010116《面向对象程序设计Java》第八周学习总结

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

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

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

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

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

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

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

随机推荐

  1. 【原创】WinForm中实现单独Time控件的方式

    WinForm默认只提供了DateTimePicker,今天的项目只用时间,不能出现日期,百撕不得骑姐(^^),也没花多少时间,随便试了一下,就成功了,分享一下. 在DateTimePicker属性中 ...

  2. AssemblyBuilder以及Activator双剑合璧

    AssemblyBuilder和Activator两个类是DispatchProxy类实现动态代理以及AOP的根本,示例demo可参考 DispatchProxy实现动态代理及AOP .Assembl ...

  3. JS---体验DOM操作

    体验DOM操作 1. <!--html代码--> <input type="button" value="弹框" onclick=" ...

  4. Tesseract.js 一个几乎能识别出图片中所有语言的JS库

    Tesseract.js 一个几乎能识别出图片中所有语言的JS库. 官网:http://tesseract.projectnaptha.com/ git:https://github.com/napt ...

  5. Windows宏病毒利用

    背景: 最近忙的飞起,各种事情,不想吐槽,因为某些事情,还吃了口屎,啧啧啧..... 常见的钓鱼,社工基本技术都是这种,什么鱼叉,水坑,社工,投毒之类的,APT 攻击惯用伎俩. 那么今天主要利用Win ...

  6. Linux系统学习 十八、VSFTP服务—虚拟用户访问—配置虚拟用户访问

    配置虚拟用户访问 首先至少要关闭userlist 改完配置文件是要重启服务来使它生效 其实在刚装好vsftp的时候的配置文件不用修改的情况下配置虚拟用户访问控制是最好的 local_root选项不影响 ...

  7. 九、ITK-VTK混合编程--将序列dcm图像通过ITK读去并通过VTK显示出来

    一.初步介绍 上一个博客里面我记录了VTK的安装,以及相关的工程代码的构建,但是实际上上一个博客测试的代码的例子仅仅只是VTK程序的例子.而我实际上希望能够实现的是VTK和ITK混合编程. 在这里还是 ...

  8. Redis学习笔记(九、Redis总结)

    1.Redis五大对象: 在Redis中有五大对象,分别是String.List.Hash.Set.Sorted Set. 这五大对象都有自己独特的编码方式,每个编码的实现都不一样,有自己独特的使用场 ...

  9. steamdb cookie

    steamdb cookie import requests, re, os, pymysql, time from lxml import etree from steamdb.YDM import ...

  10. SQL Server 索引分析开关

    set statistics io onset statistics profile on