博文正文开头格式:(2分)

项目

内容

这个作业属于哪个课程

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知识内容(20分)

14.1什么是线程

1.进程:正在执行中的程序,其实是应用程序在内存中的那片空间
  线程:进程中的一个执行单元,负责进程中程序的运行,一个进程至少有一个线程,一个进程中是可以有多个线程的,这个应用程序也可以成为多线程程序

故一个程序同时执行多个任务,通常每个任务称为一个线程。
 2.进程和线程区别
   进程拥有自己的一整套变量体系,而线程则是共享。线程是轻量的,创建撤销的开销小。

3.多进程与多线程的区别

二者的本质区别在于每个进程拥有自己的一整套变量,而线程则共享数据,这听起来似乎有些风险,的确也是这样。然而,共享变量使线程之间的通信比进程之间的通信更有效,更容易。除此之外,在有些操作系统中,与进程相比较,线程更“轻量级”,创建、撤销一个线程要比启动一个新进程的开销要小得多。

当然,在实际应用中,多线程也非常有用。例如:一个浏览器可以同时下载几幅图片、一个web服务器需要同时处理几个并发的请求、图形用户界面(GUI)程序用一个独立的线程从宿主环境中收集用户界面的事件等等。

4.线程的简单使用:

方式一:

//自定义Runnable
class MyRunnable implements Runnable{
@Override
public void run () {
//需要处理的任务
}
}
//创建Runnable对象
Runnable r = new MyRunnable();
//创建Thread对象
Thread t = new Thread(r);
//启动线程
t.start();

方式二:

//复写Thread类的run方法
Thread thread= new Thread(){
@Override
public void run () {
//需要做的任务
}
};
thread.start();

  方式二每一个任务启动一个线程不好,开销大,多任务并行处理可以通过线程池来实现。

14.2中断线程

线程终止只有两种方式:
1、run方法正常退出,自然死亡
2、因为有没有捕获的异常而终止run方法,意外死亡
stop 方法可以终止线程,但是被弃用了

当线程调用interrupt方法时,线程中断状态被置位;每个线程都有一个boolean标志,以判断线程是否被中断。

中断不等于终止,没有任务和语言上的要求,中断的线程应该终止。中断一个线程只不过是引起他的注意,被中断的线程可以决定如何响应中断。线程可以简单的将中断作为一个终止的请求。

//发送中断请求
void interrupt()
//测试当前线程(即正在执行这一命令的线程)是否被中断,副作用是会把当前线程中断状态变成false
static boolean interrupted()
//测试线程是否被中断,实例方法,不会重置中断状态
boolean isInterrupted()

  线程被阻塞时中断状态无法被检测,会抛出中断异常InterruptedException;通常是sleep,wait,IO阻塞等的情况下出现。

14.3 线程状态

1、线程一共有如下6种状态:

      New (新建)

      Runnable (可运行)

      Blocked (被阻塞)

      Waiting (等待)

      Timed waiting (计时等待)

      Terminated (被终止)

1.新创建线程:

线程的创建

new(新建) 线程对象刚刚创建,还没有启动,此时还处于不可运行状态。

Thread thread=new Thread(“test”) 此时线程thread处于新建状态,但已有了相应的内存空间以及其它资源。

通过API中的英文Thread类的查询,通过对Thread类的描述,了解到线程的创建有两种方式
(1)、继承Thread类
1.1、定义一个类,继承thread
1.2、重写run()方法
1.3、创建子类对象,就是创建线程对象
1.4、调用start方法,开启线程并让线程执行,同时还会告诉JVM调用run方法

(2)、线程创建的第二种方式:实现runable接口
2.1、定义类实现runable接口
2.2、覆盖接口中的run方法,将线程任务代码定义到run方法中
2.3、创建Thread类的对象
2.4、将runable接口的子类对象作为参数传递给Thread类的构造函数
2.5、调用Thread类的start方法开启线程

2.创建线程的目的:
   是为了建立单独的执行路径,让多部分代码实现同时执行,也就是说,线程的创建并执行需要给定的代码(线程的任务)
   对于之前创建的主线程,其任务定义在主函数中自定义的线程需要执行的任务都定义在run方法中Thread类中的run方法内部的任务并不是我们所需要的,只要重写这个run方法即可
   既然Thread类已经定义了线程任务的位置,只要在位置中定义任务代码即可,所以进行了重写run方法的动作

多线程执行时,在栈内存中,其实每一个执行线程都有一片自己所属的栈内存空间
当执行线程的任务结束了,线程自动在栈内存中释放,但当所有的线程都结束了,那么进程也就结束了

3.获取线程名称:
Thread:currentThread()获取当前线程对象。
Thread.currentThread().getName();

4.几个函数:

void join()//等待终止指定线程,让一个线程B“加入”到另外一个线程A的尾部。在A执行完毕之前,B不能工作
void join(long millis) //等待指定的线程死亡或者经过指定的毫秒数,如果超过这个时间,则停止等待,变为可运行状态
void stop()//停止该线程。这一方法已过时
void suspend() //暂停这一线程的执行 已过时
void resume() //恢复线程,和suspend一起使用,也过时
void sleep(long millis)// 等待休眠millis 毫秒,执行这个方法,线程进入计时等待
void yield()//暂停当前正在执行的线程对象,并执行其他线程。理论上,yield意味着放手,放弃,投降。
//一个调用yield()方法的线程告诉虚拟机它乐意让其他线程占用自己的位置。这表明该线程没有在做一些紧急的事情。
//注意,这仅是一个暗示,并不能保证不会产生任何影响。

第二部分:实验部分

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

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

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

13-1代码如下:

package resource;

import java.awt.*;
import java.io.*;
import java.net.*;
import java.util.*;
import javax.swing.*; /**
* A frame that loads image and text resources.
* 加载图像和文本资源的框架。
*/ 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);
URL aboutURL = getClass().getResource("about.gif");
Image img = new ImageIcon(aboutURL).getImage();
//利用about.gif图像文件制作图标;
setIconImage(img); //进行资源加载时从外村到内存 JTextArea textArea = new JTextArea();
InputStream stream = getClass().getResourceAsStream("about.txt");
//读取about.gif(当前项目目录下的文件名文件
try (Scanner in = new Scanner(stream, "UTF-8"))//规定编码标准
{
while (in.hasNext())
textArea.append(in.nextLine() + "\n");//调用append方法让内容显示到文本区
}
add(textArea);
}
}

  

运行截图:

归档:

      

         

按照如下步骤创建和引入JAR文件:
1. 创建储存包文件的目录。与利用CLASSPATH创建包文件目录的要求相同,从总目录开始,必须至少有3个子目录。如:C:\javabook\classes\ch12\
2. 将包文件(源代码文件)复制到以上目录中。
3. 分别编译每个程序。
4. 创建JAR文件。输入如下jar指令:
C:\javabook\classes\jar cvf ch12.jar ch12\*
这个指令在当前目录中产生一个包括子目录所有文件的名为ch12.jar的压缩文件。

三个jar指令的选项cvf的含义为:c——创建JAR文件;v——显示创建过程信息;f——跟随的是jar文件名。“*”表示将包括源代码在内的程序都压缩在JAR文件中。

也可以利用如下指令只包括字节文件:
C:\javabook\classess\jar cvf ch12.jar ch12\*.class

注意,一般JAR文件名使用小写字母。可以是任何Java合法标识符。

5. 将创建的jar文件拷贝到JDK的子目录\jre\lib\ext\中。

6. 实现引入。任何程序都可以引入这个JAR文件中的包类。

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

代码如下:

class Lefthand extends Thread {
public void run()
{
for(int i=0;i<=5;i++)
{ System.out.println("You are Students!");
try{ sleep(500); }//输出第一次后,程序休眠时间为500ms;
catch(InterruptedException e)
{ System.out.println("Lefthand error.");}
} //for循环执行6次,输出六次You are Students!
}
}
class Righthand extends Thread {
public void run()
{
for(int i=0;i<=5;i++)
{ System.out.println("I am a Teacher!");
try{ sleep(300); }//输出第一次后,程序休眠时间为300ms;
catch(InterruptedException e)
{ System.out.println("Righthand error.");}
}//for循环执行6次,输出六次I am a Teacher!
}
}
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();
}
}

运行截图:

修改后:

class Lefthand1 implements Runnable{
public void run()
{ for(int i=0;i<=5;i++)
{ System.out.println("You are Students!");
try{ Thread.sleep(500); }
//输出第一次后,程序休眠时间为500ms;
catch(InterruptedException e)//中断异常
{ System.out.println("Lefthand error.");}
}
}
}
class Righthand1 implements Runnable {
public void run()
{
for(int i=0;i<=5;i++)
{ System.out.println("I am a Teacher!");
try{ Thread.sleep(300); }
//输出第一次后,程序休眠时间为300ms;
catch(InterruptedException e)
{ System.out.println("Righthand error.");}
}
}
}
public class ThreadTest1
{
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分)

14-1代码如下:

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; /**
*用显示弹跳球的组件构建框架
*开始和关闭按钮
*/
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();
} /**
*向容器中添加按钮。
* @参数c容器
* @ param title按钮标题
* @ param侦听器按钮的操作侦听器
*/
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.
*向面板添加一个弹跳球,使其弹跳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)
{
}
}
}

  

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;//x比所设置框的行的左边最小值还小时,变换方向
}
if (x + XSIZE >= bounds.getMaxX())
{
x = bounds.getMaxX() - XSIZE;
dx = -dx;//x比所设置框的行的右边最大值还大时,变换方向
}
if (y < bounds.getMinY())
{
y = bounds.getMinY();
dy = -dy;//y比所设置框的列的最小值还小时,变换方向
}
if (y + YSIZE >= bounds.getMaxY())
{
y = bounds.getMaxY() - YSIZE;
dy = -dy;//y比所设置框的列的最大值还大时,变换方向
}
} /**
*获取球在其当前位置的形状。
*/
public Ellipse2D getShape()
{
return new Ellipse2D.Double(x, y, XSIZE, YSIZE);
}
}

  

package bounce;

import java.awt.*;
import java.util.*;
import javax.swing.*; /**
* The component that draws the balls.
* 拉动球的组件。
*/
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要添加的球
*/
public void add(Ball b)
{
balls.add(b);
} public void paintComponent(Graphics g) //调用paintComponent方法来进行自定义
{
super.paintComponent(g); // erase background擦出背景
Graphics2D g2 = (Graphics2D) g;
for (Ball b : balls)
{
g2.fill(b.getShape());
}
} public Dimension getPreferredSize() { return new Dimension(DEFAULT_WIDTH, DEFAULT_HEIGHT); }
}

运行截图:

        

14-4代码如下:

package bounceThread;

import java.awt.*;
import java.util.*;
import javax.swing.*; import bounce.Ball; /**
* The component that draws the balls.
* 拉动球的组件。
*/
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要添加的球
*/
public void add(Ball b)
{
balls.add(b);
} public void paintComponent(Graphics g) //调用paintComponent方法来进行自定义
{
super.paintComponent(g); // erase background擦出背景
Graphics2D g2 = (Graphics2D) g;
for (Ball b : balls)
{
g2.fill(b.getShape());
}
} public Dimension getPreferredSize() { return new Dimension(DEFAULT_WIDTH, DEFAULT_HEIGHT); }
}

  

package bounceThread;

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;//x比所设置框的行的左边最小值还小时,变换方向
}
if (x + XSIZE >= bounds.getMaxX())
{
x = bounds.getMaxX() - XSIZE;
dx = -dx;//x比所设置框的行的右边最大值还大时,变换方向
}
if (y < bounds.getMinY())
{
y = bounds.getMinY();
dy = -dy;//y比所设置框的列的最小值还小时,变换方向
}
if (y + YSIZE >= bounds.getMaxY())
{
y = bounds.getMaxY() - YSIZE;
dy = -dy;//y比所设置框的列的最大值还大时,变换方向
}
} /**
*获取球在其当前位置的形状。
*/
public Ellipse2D getShape()
{
return new Ellipse2D.Double(x, y, XSIZE, YSIZE);
}
}

  

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()
{ // BounceFrame有两个组件BallComponent和buttonPanel
comp = new BallComponent();
add(comp, BorderLayout.CENTER);
JPanel buttonPanel = new JPanel();//buttonPanel有两个组件start和close
addButton(buttonPanel, "Start", event -> addBall());
addButton(buttonPanel, "Close", event -> System.exit(0));
add(buttonPanel, BorderLayout.SOUTH);
pack();
} /**
*向容器中添加按钮。
* @参数c容器
* @ param title按钮标题
* @ param侦听器按钮的操作侦听器
*/
public void addButton(Container c, String title, ActionListener listener)//c为所加的组件
{
JButton button = new JButton(title);//利用了抽象思维方式
c.add(button);
button.addActionListener(listener);
} /**
* 在画布上添加一个弹跳球,并开始一条线使其弹跳
*/
public void addBall()
{
bounce.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();
}//将弹跳球代码放在一个独立的线程中,实现一个类BallRunnable,然后将动画代码放在run方法中
} 

运行截图:

                

根据实验结果可知,加入了线程之后,只要点击start按钮,就会有小球出现,而不加线程时, 至于当前面的一个小球开始运动至结束后,才会出现下一个小球;

实验2:结对编程练习:采用GUI界面设计以下程序,并创建程序归档文件。

设计一个100以内整数小学生四则运算练习程序,由计算机随机产生10道加减乘除练习题,学生输入答案,由程序检查答案是否正确,每道题正确计10分,错误不计分,10道题测试结束后给出测试总分;

将程序中测试练习题及学生答题结果输出到文件,文件名为test.txt。

1)程序设计思路简述;

此次结对编程设计的GUI界面,主要是用了网格布局,在其“NORTH”是创建了一个一行三列的面板,来分别存放题目,用户输入的答案以及判断其答案是否正确,然后在“SOUTH”设计了一个三个按钮,按钮的作用分别是“出题”,“判断正误”以及“生成文件”,使得最后将程序中测试练习题及学生答题结果输出到文件,文件名为test.txt;最后在界面中加入了一个文本域,来将即时的题目对错情况和得分情况进行记录;总的设计思路便是如此,主函数用的是lanmda表达式。

2) 程序代码如下:

package Test;
import java.awt.*;
import javax.swing.*; public class CeshiTest {
public static void main(String[] args) {
EventQueue.invokeLater(() -> {
JFrame frame = new Ceshi();
frame.setTitle("四则运算器");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
});
}
}

  

package Test;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.util.*;
import javax.swing.*; public class Ceshi extends JFrame {
int i = 0, m = 0;
int n = 0, sum = 0;
private PrintWriter out = null;
private JTextArea display;
private JScrollPane text;
private String[] exam = new String[50];
private String[] answer = new String[10]; public Ceshi() {
JPanel panel = new JPanel();
panel.setLayout(new GridLayout(1, 3));
JTextField timu = new JTextField();
JTextField daan = new JTextField(20);
JTextField panduan = new JTextField();
panel.add(timu);
panel.add(daan);
panel.add(panduan);
add(panel, BorderLayout.NORTH); JPanel panel1 = new JPanel();
panel1.setLayout(new GridLayout(1, 3));
Button button1 = new Button("生成题目");
Button button2 = new Button("判断正误");
Button button3 = new Button("生成文件");
panel1.add(button1);
panel1.add(button2);
panel1.add(button3);
add(panel1, BorderLayout.SOUTH);
setSize(500, 400);
button1.addActionListener(new ActionListener() { @Override
public void actionPerformed(ActionEvent e) { daan.setText(null);
panduan.setText(null);
if (i < 10) {
int a = (int) (Math.random() * 100);
int b = (int) (Math.random() * 100);
//随机产生100以内整数
int m = (int) Math.round(Math.random() * 3);
switch (m) {
case 0:
while (b == 0 || a % b != 0) {
b = (int) Math.round(Math.random() * 100);
a = (int) Math.round(Math.random() * 100);
//100以内整数
}
timu.setText("第" +(i+1)+"道" + ": " + a + "/" + b + "=");
exam[i] = timu.getText();
n = a / b;
i++;
break;
case 1:
timu.setText("第" +(i+1)+"道" + ": " + a + "*" + b + "=");
exam[i] = timu.getText();
n = a * b;
i++;
break;
case 2:
timu.setText("第" +(i+1)+"道" + ": " + a + "+" + b + "=");
exam[i] = timu.getText();
n = a + b;
i++;
break;
case 3:
while (a < b) {
int x = a;
a = b;
b = x;
}
timu.setText("第" +(i+1)+"道" + ": " + a + "-" + b + "=");
exam[i] = timu.getText();
n = a - b;
i++;
break;
}
}
}
}); button2.addActionListener(new ActionListener() { @Override
public void actionPerformed(ActionEvent e) { if (i < 11) {
int input = Integer.parseInt(daan.getText());//用户输入计算答案
String d =daan.getText().toString().trim();//输入答案
if (daan.getText() != " ") {
if (input == n) {
sum += 10;
display.append("当前成绩为" + sum+"\n");
panduan.setText("答案正确");
} else
display.append("没有成绩"+ "\n");
panduan.setText("答案错误");
}
answer[m] = d;
m++;
}
}
});
button3.addActionListener(new ActionListener() { @Override
public void actionPerformed(ActionEvent e) { try {
out = new PrintWriter("C:\\Users\\java\\Desktop\\text.txt");
} catch (FileNotFoundException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();//输出路径
}
for (int counter = 0; counter < 10; counter++) {
out.write(exam[counter] + answer[counter]+"\n");
}
out.println("最终运算成绩为" + sum);
out.close();
} }); display=new JTextArea("运算结果显示区:",60,10);
text= new JScrollPane(display);
display.setText("");
display.append("当前运算成绩为" + sum+ "\n");
System.out.println(sum);
add(text,BorderLayout.CENTER); }
}

 3)运行结果:

       

对文件进行归档:

        

实验总结:(15分)

这周学习了第十四章有关线程的基础知识点,在理论课中首先对线程的概念有了了解,然后通过老师课堂的讲解和在实验课中对课本范例的运行,对有关线程的代码中的知识点有了一定的认识,其次,

掌握线程创建的两种技术:继承Thread类和实现runable接口,通过实验中弹跳球的例子进行比较学习,对二者的区别和不同有了更深的掌握, 并且还通过结对编程的作业学习了设计应用程序的GUI。通过对知

识点的总结和应用对这一周所学的这一章的内容也有了更多的掌握。

最新文章

  1. (转)Predictive learning vs. representation learning 预测学习 与 表示学习
  2. IOS 键盘 禁止输入字母
  3. Apache二级域名配置方法
  4. 火狐谷歌浏览器Json查看插件
  5. java中的反射机制_____
  6. 《C++ Primer》之指向函数的指针
  7. jQuery实现DIV拖动
  8. 滚动条大于120px时,判断pc端的情况下,导航条固定定位
  9. Spring MVC注解式开发
  10. [bzoj4824][Cqoi2017]老C的键盘
  11. javascript显式类型转换
  12. Linux系统(四)LVS集群负载均衡NAT模式
  13. DevExpress 控件汉化代码和使用方法
  14. Python面向对象3:面向对象的三大特性
  15. iphoneX适配!!!
  16. centos7.2环境nginx+mysql+php-fpm+svn配置walle自动化部署系统详解
  17. Pytorch的torch.cat实例
  18. Spark交互式工具spark-shell
  19. 关于STM32位带操作随笔
  20. 【openjudge】【字符串】P6374文字排版

热门文章

  1. 攻防世界web之ics-05
  2. 【2019.8.11下午 慈溪模拟赛 T2】数数(gcd)(分块+枚举因数)
  3. windows/tomcat 修改java虚拟机JVM以utf-8字符集加载class文件的两种方式
  4. Unity开发实战探讨-资源的加载释放最佳策略简要心得
  5. 【08月14日】A股ROE最高排名
  6. npm ERR! Cannot read property &#39;resolve&#39; of undefined
  7. 【Oracle】 RMAN命令汇总
  8. css3的user-select属性设置文本内容能否被选择
  9. ssh框架被淘汰的原因
  10. C# 之扩展方法