201871010104-陈园园《面向对象程序设计(java)》第十六周学习总结

项目 内容
这个作业属于哪个课程 https://www.cnblogs.com/nwnu-daizh/
这个作业要求在哪里 https://www.cnblogs.com/lily-2018/p/11441372.html
作业学习目标

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

(2) 掌握线程概念;

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

第一部分:总结理论知识

线程的组成

线程ID:线程标识符。

    • 当前指令指针(PC):指向要执行的指令。

      寄存器集合:存储单元寄存器的集合。

      堆栈:暂时存放数据和地址,一般用来保护断点和现场。

      线程与进程区别

      线程和进程之间的区别,我觉得可以用这个例子来看出两者的不同,进程就是一栋房子,房子住着 3 个人,线程就是住在房子里的人。进程是一个独立的个体,有自己的资源,线程是在进程里的,多个线程共享着进程的资源。

      线程状态

      我们看到 Java 源代码里面,线程状态的枚举有如下 6 个。

      1. public enum State {
      2. //新建状态
      3. NEW,
      4. //运行状态
      5. RUNNABLE,
      6. //阻塞状态
      7. BLOCKED,
      8. //等待状态
      9. WAITING,
      10. //等待状态(区别在于这个有等待的时间)
      11. TIMED_WAITING,
      12. //终止状态
      13. TERMINATED;
      14. }

      下面给这 6 个状态一一做下解释。

      NEW:新建状态。在创建完 Thread ,还没执行 start() 之前,线程的状态一直是 NEW。可以说这个时候还没有真正的一个线程映射着,只是一个对象。

      RUNNABLE:运行状态。线程对象调用 start() 之后,就进入 RUNNABLE 状态,该状态说明在 JVM 中有一个真实的线程存在。

      BLOCKED:阻塞状态。线程在等待锁的释放,也就是等待获取 monitor 锁。

      WAITING:等待状态。线程在这个状态的时候,不会被分配 CPU,而且需要被显示地唤醒,否则会一直等待下去。

      TIMED_WAITING:超时等待状态。这个状态的线程也一样不会被分配 CPU,但是它不会无限等待下去,有时间限制,时间一到就停止等待。

      TERMINATED:终止状态。线程执行完成结束,但不代表这个对象已经没有了,对象可能还是存在的,只是线程不存在了。

      线程既然有这么多个状态,那肯定就有状态机,也就是在什么情况下 A 状态会变成 B 状态。下面就来简单描述一下。

      结合下图,我们 new 出线程类的时候,就是 NEW 状态,调用 start() 方法,就进入了 RUNNABLE 状态,这时如果触发等待,则进入了 WAITING 状态,如果触发超时等待,则进入 TIMED_WAITING 状态,当访问需要同步的资源时,则只有一个线程能访问,其他线程就进入 BLOCKED 状态,当线程执行完后,进入 TERMINATED 状态。

      线程的组成

      线程ID:线程标识符。

      当前指令指针(PC):指向要执行的指令。

      寄存器集合:存储单元寄存器的集合。

      堆栈:暂时存放数据和地址,一般用来保护断点和现场。

      线程与进程区别

      线程和进程之间的区别,我觉得可以用这个例子来看出两者的不同,进程就是一栋房子,房子住着 3 个人,线程就是住在房子里的人。进程是一个独立的个体,有自己的资源,线程是在进程里的,多个线程共享着进程的资源。

      线程状态

      我们看到 Java 源代码里面,线程状态的枚举有如下 6 个。

      1. public enum State {
      2. //新建状态
      3. NEW,
      4. //运行状态
      5. RUNNABLE,
      6. //阻塞状态
      7. BLOCKED,
      8. //等待状态
      9. WAITING,
      10. //等待状态(区别在于这个有等待的时间)
      11. TIMED_WAITING,
      12. //终止状态
      13. TERMINATED;
      14. }

      下面给这 6 个状态一一做下解释。

      NEW:新建状态。在创建完 Thread ,还没执行 start() 之前,线程的状态一直是 NEW。可以说这个时候还没有真正的一个线程映射着,只是一个对象。

      RUNNABLE:运行状态。线程对象调用 start() 之后,就进入 RUNNABLE 状态,该状态说明在 JVM 中有一个真实的线程存在。

      BLOCKED:阻塞状态。线程在等待锁的释放,也就是等待获取 monitor 锁。

      WAITING:等待状态。线程在这个状态的时候,不会被分配 CPU,而且需要被显示地唤醒,否则会一直等待下去。

      TIMED_WAITING:超时等待状态。这个状态的线程也一样不会被分配 CPU,但是它不会无限等待下去,有时间限制,时间一到就停止等待。

      TERMINATED:终止状态。线程执行完成结束,但不代表这个对象已经没有了,对象可能还是存在的,只是线程不存在了。

      线程既然有这么多个状态,那肯定就有状态机,也就是在什么情况下 A 状态会变成 B 状态。下面就来简单描述一下。

      结合下图,我们 new 出线程类的时候,就是 NEW 状态,调用 start() 方法,就进入了 RUNNABLE 状态,这时如果触发等待,则进入了 WAITING 状态,如果触发超时等待,则进入 TIMED_WAITING 状态,当访问需要同步的资源时,则只有一个线程能访问,其他线程就进入 BLOCKED 状态,当线程执行完后,进入 TERMINATED 状态。

Java 中如何创建一个线程

继承 Thread 类,重写 run() 方法。

  1. class MyThread extends Thread {
  2.  
  3. @Override
  4. public void run() {
  5. System.out.println("MyThread");
  6. }
  7.  
  8. }

实现 Runnable 接口,实现 run() 方法。

  1. class MyRunnable implements Runnable {
  2.  
  3. public void run() {
  4. System.out.println("MyRunnable");
  5. }
  6.  
  7. }

  这 2 种线程的启动方式也不一样。MyThread 是一个线程类,所以可以直接 new 出一个对象出来,接着调用 start() 方法来启动线程;而 MyRunnable 只是一个普通的类,需要 new 出线程基类 Thread 对象,将 MyRunnable 对象传进去。

线程在Running的过程中可能会遇到阻塞(Blocked)情况:

  • 调用join()sleep()方法,sleep()时间结束或被打断,join()中断,IO完成都会回到Runnable状态,等待JVM的调度。
  • 调用wait(),使该线程处于等待池(wait blocked pool),直到notify()/notifyAll(),线程被唤醒被放到锁定池(lock blocked pool ),释放同步锁使线程回到可运行状态(Runnable)
  • 对Running状态的线程加同步锁(Synchronized)使其进入(lock blocked pool ),同步锁被释放进入可运行状态(Runnable)。

1.实现Runnable接口,重载run(),无返回值,Runnable接口的存在主要是为了解决Java中不允许多继承的问题。

2.继承Thread类,重写run(),通过调用Thread的start()会调用创建线程的run(),不同线程的run方法里面的代码交替执行。但由于Java不支持多继承.因此继承Thread类就代表这个子类不能继承其他类.

    • 同步:synchronized,同步的概念就是共享,只需要针对共享的资源,才需要考虑同步。

线程同步,是指线程之间所具有的一种制约关系,一个线程的执行依赖另一个线程的消息,当它没有得到另一个线程的消息时应等待,直到消息到达时才被唤醒。

线程中断机制是一种协作机制,也就是说通过中断并不能直接终止另一个线程,而需要被中断的线程自己处理。

三个中断方法:

1、interrupt()

2、isInterrupted():方法唯一的作用只是测试线程是否已经中断。

3、interrupted():方法的作用是测试当前线程是否已经中断,线程的中断标识位由该方法清除。

线程终止:

1、使用 volatile 关键字修饰 变量的方式终止

2、使用 interrupt() 方式终止

3、Stop 方法终止

可以直接使用thread.stop()来强行终止线程,但是stop方法是很危险的,就象突然关闭计算机电源,而不是按正常程序关机一样,可能会产生不可预料的结果。

线程处于阻塞状态
线程处于阻塞状态,如使用了sleep,同步锁的wait,socket中的receiver,accept等方法时,会使线程处于阻塞状态。当调用线程的interrupt()方法时,会抛出InterruptException异常。阻塞中的那个方法抛出这个异常,通过代码捕获该异常,然后break跳出循环状态,从而让我们有机会结束这个线程的执行。

第二部分:实验测试

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

测试程序1

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

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

掌握创建JAR文件的方法;

  1. import java.awt.*;
  2. import java.io.*;
  3. import java.net.*;
  4. import java.util.*;
  5. import javax.swing.*;
  6.  
  7. /**
  8. * @version 1.41 2015-06-12
  9. * @author Cay Horstmann
  10. */
  11. public class ResourceTest
  12. {
  13. public static void main(String[] args)
  14. {
  15. EventQueue.invokeLater(() -> {
  16. JFrame frame = new ResourceTestFrame();
  17. frame.setTitle("ResourceTest");
  18. frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  19. frame.setVisible(true);
  20. });
  21. }
  22. }
  23.  
  24. /**
  25. * A frame that loads image and text resources.
  26. */
  27. class ResourceTestFrame extends JFrame
  28. {
  29. private static final int DEFAULT_WIDTH = 300;
  30. private static final int DEFAULT_HEIGHT = 300;//定义窗口宽和高
  31.  
  32. public ResourceTestFrame()//构造器
  33. {
  34. setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT);
  35. URL aboutURL = getClass().getResource("about.gif");//URL来指向about.gif资源地址
  36. Image img = new ImageIcon(aboutURL).getImage();//利用about.gif图像文件制作图标,在找到ResourceTest类的地方查找about.gif文件
  37. setIconImage(img);
  38.  
  39. JTextArea textArea = new JTextArea();//创建文本区
  40. InputStream stream = getClass().getResourceAsStream("about.txt");//读取about.txt文件
  41. try (Scanner in = new Scanner(stream, "UTF-8"))
  42. {
  43. while (in.hasNext())
  44. textArea.append(in.nextLine() + "\n");
  45. }
  46. add(textArea);
  47. }
  48. }

运行结果:

测试程序2:

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

2) 掌握线程概念;

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

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

  1. class Lefthand extends Thread {
  2. public void run()
  3. {
  4. for(int i=0;i<=5;i++)
  5. { System.out.println("You are Students!");
  6. try{ sleep(500); }
  7. catch(InterruptedException e)
  8. { System.out.println("Lefthand error.");}
  9. }
  10. }
  11. }
  12. class Righthand extends Thread {
  13. public void run()
  14. {
  15. for(int i=0;i<=5;i++)
  16. { System.out.println("I am a Teacher!");
  17. try{ sleep(300); }
  18. catch(InterruptedException e)
  19. { System.out.println("Righthand error.");}
  20. }
  21. }
  22. }
  23. public class ThreadTest
  24. {
  25. static Lefthand left;
  26. static Righthand right;
  27. public static void main(String[] args)
  28. { left=new Lefthand();
  29. right=new Righthand();
  30. left.start();
  31. right.start();
  32. }
  33. }

 运行结果:

 

测试程序3:

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

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

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

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

  1. import java.awt.*;
  2. import java.util.*;
  3. import javax.swing.*;
  4.  
  5. /**
  6. * The component that draws the balls.
  7. * @version 1.34 2012-01-26
  8. * @author Cay Horstmann
  9. */
  10. public class BallComponent extends JPanel
  11. {
  12. private static final int DEFAULT_WIDTH = ;
  13. private static final int DEFAULT_HEIGHT = ;
  14.  
  15. private java.util.List<Ball> balls = new ArrayList<>();
  16.  
  17. /**
  18. * Add a ball to the component.
  19. * @param b the ball to add
  20. */
  21. public void add(Ball b)
  22. {
  23. balls.add(b);
  24. }
  25.  
  26. public void paintComponent(Graphics g)
  27. {
  28. super.paintComponent(g); // 擦除背景
  29. Graphics2D g2 = (Graphics2D) g;
  30. for (Ball b : balls)
  31. {
  32. g2.fill(b.getShape());
  33. }
  34. }
  35.  
  36. public Dimension getPreferredSize()
  37. {
  38. return new Dimension(DEFAULT_WIDTH, DEFAULT_HEIGHT); }
  39. }
  1. import java.awt.*;
  2. import java.awt.event.*;
  3. import javax.swing.*;
  4.  
  5. /**
  6. * Shows an animated bouncing ball.
  7. * @version 1.34 2015-06-21
  8. * @author Cay Horstmann
  9. */
  10. public class Bounce
  11. {
  12. public static void main(String[] args)
  13. {
  14. EventQueue.invokeLater(() -> {
  15. JFrame frame = new BounceFrame();
  16. frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  17. frame.setVisible(true);
  18. });
  19. }
  20. }
  21.  
  22. /**
  23. * The frame with ball component and buttons.
  24. */
  25. class BounceFrame extends JFrame
  26. {
  27. private BallComponent comp;
  28. public static final int STEPS = ;
  29. public static final int DELAY = ;
  30.  
  31. /**
  32. * Constructs the frame with the component for showing the bouncing ball and
  33. * Start and Close buttons
  34. */
  35. public BounceFrame()
  36. {
  37. setTitle("Bounce");
  38. comp = new BallComponent();
  39. add(comp, BorderLayout.CENTER);//使用边框布局管理器使其显示在窗口中心位置
  40. JPanel buttonPanel = new JPanel();
  41. addButton(buttonPanel, "Start", event -> addBall());//在窗口添加两个按钮
  42. addButton(buttonPanel, "Close", event -> System.exit());
  43. add(buttonPanel, BorderLayout.SOUTH);//使用边框布局管理器使其显示在窗口下方位置
  44. pack();
  45. }
  46.  
  47. /**
  48. * Adds a button to a container.
  49. * @param c the container
  50. * @param title the button title
  51. * @param listener the action listener for the button
  52. */
  53. public void addButton(Container c, String title, ActionListener listener)
  54. {
  55. JButton button = new JButton(title);
  56. c.add(button);
  57. button.addActionListener(listener);
  58. }
  59.  
  60. /**
  61. * Adds a bouncing ball to the panel and makes it bounce 1,000 times.
  62. */
  63. public void addBall()
  64. {
  65. try
  66. {
  67. Ball ball = new Ball();
  68. comp.add(ball);
  69.  
  70. for (int i = ; i <= STEPS; i++)
  71. {
  72. ball.move(comp.getBounds());
  73. comp.paint(comp.getGraphics());
  74. Thread.sleep(DELAY);
  75. }
  76. }
  77. catch (InterruptedException e)
  78. {
  79. }
  80. }
  81. }
  1. import java.awt.geom.*;
  2.  
  3. /**
  4. * A ball that moves and bounces off the edges of a rectangle
  5. * @version 1.33 2007-05-17
  6. * @author Cay Horstmann
  7. */
  8. public class Ball
  9. {
  10. private static final int XSIZE = 15;
  11. private static final int YSIZE = 15;
  12. private double x = 0;
  13. private double y = 0;
  14. private double dx = 1;
  15. private double dy = 1;
  16.  
  17. /**
  18. * 将球移动到下一个位置,如果球碰到其中一条边,则反向移动
  19. */
  20. public void move(Rectangle2D bounds)
  21. {
  22. x += dx;
  23. y += dy;
  24. if (x < bounds.getMinX())
  25. {
  26. x = bounds.getMinX();
  27. dx = -dx;
  28. }
  29. if (x + XSIZE >= bounds.getMaxX())
  30. {
  31. x = bounds.getMaxX() - XSIZE;
  32. dx = -dx;
  33. }
  34. if (y < bounds.getMinY())
  35. {
  36. y = bounds.getMinY();
  37. dy = -dy;
  38. }
  39. if (y + YSIZE >= bounds.getMaxY())
  40. {
  41. y = bounds.getMaxY() - YSIZE;
  42. dy = -dy;
  43. }
  44. }
  45.  
  46. /**
  47. *获取球在当前位置的形状。
  48. */
  49. public Ellipse2D getShape()
  50. {
  51. return new Ellipse2D.Double(x, y, XSIZE, YSIZE);
  52. }
  53. }

  运行结果:

  1. package bounceThread;
  2.  
  3. import java.awt.*;
  4. import java.awt.event.*;
  5.  
  6. import javax.swing.*;
  7.  
  8. /**
  9. * Shows animated bouncing balls.
  10. * @version 1.34 2015-06-21
  11. * @author Cay Horstmann
  12. */
  13. public class BounceThread
  14. {
  15. public static void main(String[] args)
  16. {
  17. EventQueue.invokeLater(() -> {
  18. JFrame frame = new BounceFrame();
  19. frame.setTitle("BounceThread");
  20. frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  21. frame.setVisible(true);
  22. });
  23. }
  24. }
  25.  
  26. /**
  27. * The frame with panel and buttons.
  28. */
  29. class BounceFrame extends JFrame
  30. {
  31. private BallComponent comp;
  32. public static final int STEPS = 1000;
  33. public static final int DELAY = 5;
  34.  
  35. /**
  36. * Constructs the frame with the component for showing the bouncing ball and
  37. * Start and Close buttons
  38. */
  39. public BounceFrame()
  40. {
  41. comp = new BallComponent();
  42. add(comp, BorderLayout.CENTER);//使用边框布局管理器将它放在窗口的中心位置
  43. JPanel buttonPanel = new JPanel();
  44. addButton(buttonPanel, "Start", event -> addBall());
  45. addButton(buttonPanel, "Close", event -> System.exit(0));
  46. add(buttonPanel, BorderLayout.SOUTH);//使用边框布局管理器将它放在窗口的中心位置
  47. pack();
  48. }
  49.  
  50. /**
  51. * Adds a button to a container.
  52. * @param c the container
  53. * @param title the button title
  54. * @param listener the action listener for the button
  55. */
  56. public void addButton(Container c, String title, ActionListener listener)
  57. {
  58. JButton button = new JButton(title);
  59. c.add(button);
  60. button.addActionListener(listener);
  61. }
  62.  
  63. /**
  64. * Adds a bouncing ball to the canvas and starts a thread to make it bounce
  65. */
  66. public void addBall()
  67. {
  68. Ball ball = new Ball();
  69. comp.add(ball);
  70. Runnable r = () -> {
  71. try
  72. {
  73. for (int i = 1; i <= STEPS; i++)
  74. {
  75. ball.move(comp.getBounds());
  76. comp.repaint();
  77. Thread.sleep(DELAY);
  78. }
  79. }
  80. catch (InterruptedException e)
  81. {
  82. }
  83. };
  84. Thread t = new Thread(r);
  85. t.start();//调用Thread类中的start方法
  86. }
  87. }

  运行结果:

实验总结:

      在上节课的基础之上,又了解了一些新的知识,学习了并发,线程的创建,中断线程,线程与进程的区别,以及多线程问题等。除了之前了解的一些基础代码之外,又学会了很多其他新的代码知识以及所表示的不同含义与用法。后一节课在老师的讲解下学习了同步。java就这样学完了,以后慢慢回顾反思。

201871010104-陈园园《面向对象程序设计(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. pycharm 远程连接

    1.连接远程项目 2.连接远程服务器

  2. 剑指Offer-12.数值的整数次方(C++/Java)

    题目: 给定一个double类型的浮点数base和int类型的整数exponent.求base的exponent次方.   保证base和exponent不同时为0 分析: 注意base为0和expo ...

  3. 当usbnet打印 kevent * may have been dropped(转)

    http://patchwork.ozlabs.org/patch/815639/ Every once in a while when my system is under a bit of str ...

  4. kafka_2.12-2.2.1 集群搭建

    一.zookeeper集群搭建 kafka集群依赖于zookeeper的集群,搭建zookeeper集群的步骤参考我之前写过的,Solr集群搭建详细教程(一)中的第二步 二.下载解压 去官网下载htt ...

  5. ZooKeeper 入门看这篇就够了

    什么是 ZooKeeper? ZooKeeper 是一个分布式的,开放源码的分布式应用程序协同服务.ZooKeeper 的设计目标是将那些复杂且容易出错的分布式一致性服务封装起来,构成一个高效可靠的原 ...

  6. Prometheus神器之监控K8s集群

    Prometheus 简介 Prometheus是SoundCloud开源的一款开源软件.它的实现参考了Google内部的监控实现,与源自Google的Kubernetes结合起来非常合适.另外相比i ...

  7. 一个利用 Parallel.For 并行处理任务,带有进度条(ProgressBar)的 WinForm 实例(下)

    接着上一篇:一个利用 Parallel.For 并行处理任务,带有进度条(ProgressBar)的 WinForm 实例(上) 直接贴代码了: using System; using System. ...

  8. 使用Charles进行HTTPS抓包及常见问题

    在渗透过程中,需要对每一个参数,每一个接口,每一个业务逻辑构建测试用例,为此,抓包分析是必不可少的一个过程.在PC端,Burpsuite成为了渗透必备的神器,然而,使用Burpsuite有时候抓取不到 ...

  9. ASP.NET Core中的jQuery Unobtrusive Ajax帮助器

    最近在ASP.NET Core下写文章管理系统时,准备在分页显示文章内容时,使用Ajax.网上找了篇帖文,简单翻一下,仅供自己查阅. 原链接:https://dotnetthoughts.net/jq ...

  10. Java生鲜电商平台-提现模块的设计与架构

    Java生鲜电商平台-提现模块的设计与架构 补充说明:生鲜电商平台-提现模块的设计与架构,提现功能指的卖家把在平台挣的钱提现到自己的支付宝或者银行卡的一个过程. 功能相对而言不算复杂,有以下几个功能需 ...