多线程【第二十章】

 

线程简介


世间有很多工作都是可以同时完成的。例如,人体可以同时进行呼吸、血液循环、思考问题等活动;用户既可以使用计算机听歌,也可以使用它打印文件。同样,计算机完全可以将多种活动同时进行,这种思想放在 Java 中被称为并发,而将并发完成的每一件事情称为线程。在 Java 中,并发机制非常重要。在以往的程序设计中,我们都是一个任务完成后再进行下一个任务,这样下一个任务的开始必须等待前一个任务的结束。Java 语言提供了并发机制,程序员可以在程序中执行多个线程,每一个线程完成一个功能,并与其他线程并发执行,这种机制被称为多线程。然
而,有必要强调的是,并不是所有编程语言都支持多线程。

创建线程

 继承 Thread 类

Thread 类是java.lang 包中的一个类,从这个类中实例化的对象代表线程,程序员启动一个新线程需要建立 Thread实例。Thread 类中常用的两个构造方法如下:

  • public Thread(String threadName): 创建一个名称为threadName 的线程对象
  • public Thread0:创建一个新的线程对象。

继承Thread 类创建一个新的线程的语法如下:

public class ThreadTest extends Thread{
}

完成线程真正功能的代码放在类的 run0方法中,当一个类继承 Thread 类后,就可以在该类中覆盖

run0方法,将实现该线程功能的代码写入 run0方法中,然后调用 Thread 类中的 start0方法执行线程,Thread 对象需要一个任务来执行,任务是指线程在启动时执行的工作,该工作的功能代码被写在也就是调用run0方法。run0方法中。run0方法必须使用以下语法格式:

public void run(){
}

当执行一个线程程序时,就自动产生一个线程,主方法正是在这个线程上运行的。当不再启动其他线程时,该程序就为单线程程序,如本章以前的程序都是单线程程序。主方法线程启动由Java虚拟机负责,程序员负责启动自己的线程。代码如下:

publlc atatic void main(Stringll args) {
now ThreadTest().start();}

例题1

package twentieth;public class ThreadTest extends Thread{public void run() {for(int i=1;i<=10;i++) {System.out.print(i+" ");}}public static void main(String[] args) {ThreadTest th = new ThreadTest();th.start();}}//例题1

实现 Runnable 接口

到目前为止,线程都是通过扩展 Thread 类来创建的,如果程序员需要继承其他类(非 Thread类),而且还要使当前类实现多线程,那么可以通过 Runnable 接口来实现。例如,一个扩展JFrame类的GUI程序不可能再继承 Thread 类,因为 Java 语言中不支持多继承,这时该类就需要实现 Runnable 接口使其具有使用线程的功能。实现 Runnable 接口的语法如下:
 

public class Thread extends Object implements Runnable

 实现 Runnable 接口的程序会创建一个 Thread 对象,并将 Runnable 对象与 Thread 对象相关联。Thread
类中有以下两个构造方法:

  • public Thread(Runnable target)。
  • public Thread(Runnable target,String name)。

这两个构造方法的参数中都存在 Runnable 实例,使用以上构造方法就可以将 Runnable 实例与Thread 实例相关联。
使用Runnable 接口启动新的线程的步骤如下:

  • (1)建立Runnable 对象。
  • (2)使用参数为Runnable 对象的构造方法创建 Thread 实例
  • (3)调用 start0方法启动线程。

通过 Runnable 接口创建线程时,程序员首先需要编写一个实现 Runnable 接口的类,然后实例化该类的对象这样就建立了 Runnable 对象;接下来使用相应的构造方法创建Thread实例;最后使用该实例调用Thread 类中的start0方法启动线程。图202表明了实现Runnable 接口创建线程的流程。

线程最引人注目的部分应该是与 Swing 相结合创建GUT 程序,下面演示一个 GUI 程序,该程序实现了图标滚动的功能。

例题2

package twentieth;import java.awt.Container;import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;public class SwingAndThread  extends JFrame{int count = 0;public SwingAndThread() {setBounds(300,200,250,100);Container container = getContentPane();container.setLayout(null);Icon icon = new ImageIcon("src\\1.gif");JLabel jl = new JLabel(icon);jl.setBounds(10,10,200,50);Thread t = new Thread() {public void run() {while(true){jl.setBounds(count,10,200,50);try {Thread.sleep(500);}catch(InterruptedException e) {e.printStackTrace();}count += 4;if(count>=200) {count = 10;}}}};t.start(); // 启动线程container.add(jl); // 将标签添加到容器中setVisible(true); // 使窗体可见// 设置窗体的关闭方式setDefaultCloseOperation(EXIT_ON_CLOSE);}public static void main(String[] args) {// TODO Auto-generated method stubnew SwingAndThread();}}

 

线程的生命周期


线程具有生命周期,其中包含 7 种状态,分别为出生状态、就绪状态、运行状态、等待状态、休眠状态、阻塞状态和死亡状态。出生状态就是线程被创建时处于的状态,在用户使用该线程实例调用start0方法之前线程都处于出生状态; 当用户调用 start0方法后,线程处于就绪状态(又被称为可执行
状态):当线程得到系统资源后就进入运行状态。~旦线程进入可执行状态,它会在就绪与运行状态下转换,同时也有可能进入等待、休眠、阴塞或死亡状态。当处于运行状态下的线程调用 Thread 类中的 wait0方法时,该线程便进入等待状态,进入等待状态的线程必须调用 Thread 类中的 notify0方法才能被唤醒,而调用 notifyAll0方法可将所有处干等待状态下的线程唤醒;当线程调用 Thread 类中的 sleep0方法时,则会进入休眠状态。如果一个线程在运行状态下发出输入/输出请求,该线程将进入阻塞状态,在其等待输入/输出结束时线程进入就绕状态,对于阳塞的线程来说,即使系统资源空闲,线程依然不能回到运行状态。当线程的 run0方法执行完毕时,线程进入死亡状态

 操作线程的方法


操作线程有很多方法,这些方法可以使线程从某一种状态过渡到另一种状态。

线程的休眠


一种能控制线程行为的方法是调用 sleep0方法,sleep0方法需要一个参数用于指定该线程休眠的时间,该时间以毫秒为单位。在前面的实例中,已经演示过 sleep0方法,它通常是在 run0方法内的循环中被使用。sleep0方法的语法如下:

try(
Thread.sleep(2000);
)catch(InterruptedException e)
e.printStackTrace();


上述代码会使线程在 2 秒之内不会进入就绪状态。由于 sleep0方法的执行有可能抛出
InterruptedException 异常,所以将 sleep0方法的调用放在 try-catch 块中。虽然使用了 sleep0方法的线程在一段时间内会醒来,但是并不能保证它醒来后进入运行状态,只能保证它进入就绪状态。为了使读者更深入地了解线程的休眠方法,来看下面的实例。

例题3

package twentieth;import java.awt.Color;
import java.awt.Graphics;
import java.util.Random;import javax.swing.JFrame;public class SleepMethodTest  extends JFrame{private static Color[] color = { Color.BLACK, Color.BLUE, Color.CYAN, Color.GREEN, Color.ORANGE, Color.YELLOW,Color.RED, Color.PINK, Color.LIGHT_GRAY }; // 定义颜色数组private static final Random rand = new Random(); // 创建随机对象private static Color getC() { // 获取随机颜色值的方法return color[rand.nextInt(color.length)];}public SleepMethodTest() {Thread t = new Thread(new Runnable() { // 创建匿名线程对象int x = 30; // 定义初始坐标int y = 50;public void run() { while (true) { // 无限循环try {Thread.sleep(100); // 线程休眠0.1秒} catch (InterruptedException e) {e.printStackTrace();}Graphics graphics = getGraphics(); // 获取组件绘图上下文对象graphics.setColor(getC()); // 设置绘图颜色graphics.drawLine(x, y, 100, y++); // 绘制直线并递增垂直坐标if (y >= 80) {y = 50;}}}});t.start(); // 启动线程}public static void main(String[] args) {// TODO Auto-generated method stubinit(new SleepMethodTest(), 100, 100);}public static void init(JFrame frame, int width, int height) { // 初始化程序界面的方法frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);frame.setSize(width, height);frame.setVisible(true);}}

线程的加入


如果当前某程序为多线程程序,假如存在一个线程 A,现在需要插入线程 B,并要求线程 B 先行完,然后再续执行线程A,此时可以使用 Thread 类中的jin0方法来完成。这就好比此时读者在看电视,突然有人上门收水费,读者必须付完水费后才能继续看电视。当某个线程使用 join0方法加入另外一个线程时,另一个线程会等待该线程执行完毕后再继续行。下面来看一个使用join0方法的实例。

例题4

package twentieth;
import java.awt.BorderLayout;
import javax.swing.*;public class JoinTest extends JFrame {private Thread threadA; // 定义两个线程private Thread threadB;private JProgressBar progressBar = new JProgressBar(); // 定义两个进度条组件private JProgressBar progressBar2 = new JProgressBar();public static void main(String[] args) {JoinTest test = new JoinTest();test.setVisible(true);}public JoinTest() {setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);setBounds(200, 200, 200, 100);getContentPane().add(progressBar, BorderLayout.NORTH); // 将进度条设置在窗体最北面getContentPane().add(progressBar2, BorderLayout.SOUTH); // 将进度条设置在窗体最南面progressBar.setStringPainted(true); // 设置进度条显示数字字符progressBar2.setStringPainted(true);// 使用匿名内部类形式初始化Thread实例threadA = new Thread(new Runnable() {int count = 0;public void run() { // 重写run()方法while (true) {progressBar.setValue(++count); // 设置进度条的当前值try {Thread.sleep(100); // 使线程A休眠100毫秒threadB.join(); // 使线程B调用join()方法} catch (InterruptedException e) {e.printStackTrace();}}}});threadA.start(); // 启动线程AthreadB = new Thread(new Runnable() {int count = 0;public void run() {while (true) {progressBar2.setValue(++count); // 设置进度条的当前值try {Thread.sleep(100); // 使线程B休眠100毫秒} catch (InterruptedException e) {e.printStackTrace();}if (count == 100) // 当count变量增长为100时break; // 跳出循环}}});threadB.start(); // 启动线程B}
}

 线程的中断


以往有的时候会使用 stop0方法停止线程,但当前版本的 JDK 早已废除了 stop0方法,不建议使用stop0方法来停止一个线程的运行。现在提倡在 run0方法中使用无限循环的形式,然后使用一个布尔型
标记控制循环的停止。如果线程是因为使用了 sleep0或 wait0方法进入了就绪状态,可以使用 Thread 类中 interrupt0方法使线程离开run0方法,同时结束线程,但程序会抛出 InterruptedException 异常,用户可以在处理该异常时完成线程的中断业务处理,如终止 while 循环。
下面的实例演示了某个线程使用 interrupted0方法,同时程序抛出了 InterruptedException 异常,在异常处理时结束了 while 循环。在项目中,经常在这里执行关闭数据库连接和关闭 Socket 连接等操作

例题5

package twentieth;import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JProgressBar;public class InterruptedSwing extends JFrame {public static void main(String[] args) {init(new InterruptedSwing(), 100, 100);}public InterruptedSwing() {JProgressBar progressBar = new JProgressBar(); // 创建进度条getContentPane().add(progressBar, BorderLayout.NORTH); // 将进度条放置在窗体合适位置JButton button = new JButton("停止");getContentPane().add(button, BorderLayout.SOUTH);progressBar.setStringPainted(true); // 设置进度条上显示数字Thread t = new Thread(new Runnable() {int count = 0;public void run() {while (true) {progressBar.setValue(++count); // 设置进度条的当前值try {Thread.sleep(100); // 使线程休眠100毫秒} catch (InterruptedException e) { // 捕捉InterruptedException异常System.out.println("当前线程序被中断");break;}}}});button.addActionListener(new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {t.interrupt(); // 中断线程}});t.start(); // 启动线程}public static void init(JFrame frame, int width, int height) {frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);frame.setSize(width, height);frame.setVisible(true);}
}

线程的礼让

Thread 类中提供了一种礼让方法,使用 ield0方法表示,它只是给当前正处于运行状态的线程一个提醒,告知它可以将资源礼让给其他线程,但这仅是一种暗示,没有任何一种机制保证当前线程会将资源礼让

 线程的优先级


每个线程都具有各自的优先级,线程的优先级可以表明在程序中该线程的重要性,如果有很多线程处于就绪状态,系统会根据优先级来决定首先使哪个线程进入运行状态。但这并不意味着低优先级的线程得不到运行,而只是它运行的概率比较小,如垃圾回收线程的优先级就较低。
Thread 类中包含的成员变量代表了线程的某些优先级,如 Thread.MIN_PRIORITY (常数 1)ThreadMAX PRIORITY(常数 10)、ThreadNORM PRIORITY(常数 5)。其中,每个线程的优先级都在 ThreadMIN PRIORITY~ThreadMAX PRIORITY,在默认情况下其优先级都是 Thread.NORMPRIORITY。每个新产生的线程都继承了父线程的优先级。
在多任务操作系统中,每个线程都会得到一小段 CPU 时间片运行,在时间结束时,将轮换另一个线程进入运行状态,这时系统会选择与当前线程优先级相同的线程予以运行。系统始终选择就绪状态下优先级较高的线程进入运行状态。处于各个优先级状态

例题6

package twentieth;public class PriorityTest implements Runnable {String name;public PriorityTest(String name) {this.name = name;}@Overridepublic void run() {String tmp = "";for (int i = 0; i < 50000; i++) {// 完成五万次字符串拼接tmp += i;}System.out.println(name + "线程完成任务");}public static void main(String[] args) {Thread a = new Thread(new PriorityTest("A"));a.setPriority(1);// A线程优先级最小Thread b = new Thread(new PriorityTest("B"));b.setPriority(3);Thread c = new Thread(new PriorityTest("C"));c.setPriority(7);Thread d = new Thread(new PriorityTest("D"));d.setPriority(10);// D线程优先级最大a.start();b.start();c.start();d.start();}
}

要当另一个线程完成时,才会继续刚开始时间不够的线程

线程同步

在单线程程序中,每次只能做一件事情,后面的事情需要等待前面的事情完成后才可以进行,但是如果使用多线程程序,就会发生两个线程抢占资源的问题,如两个人同时说话、两个人同时过同-个独木桥等。所以,在多线程编程中需要防止这些资源访问的冲突。Java 提供了线程同步的机制来止资源访问的冲突

线程安全


实际开发中,使用多线程程序的情况很多,如银行排号系统、火车站售票系统等。这种多线程的程序通常会发生问题,以火车站售票系统为例,在代码中判断当前票数是否大于 0,如果大于0则执行将该票出售给乘客的功能,但当两个线程同时访问这段代码时(假如这时只剩下一张票),第一个线程将票售出,与此同时第二个线程也已经执行完成判断是否有票的操作,并得出票数大于 0 的结论,于是它也执行售出操作,这样就会产生负数。所以,在编写多线程程序时,应该考虑到线程安全问题。实质上线程安全问题来源于两个线程同时存取单一对象的数据。

线程同步机制


那么,该如何解决资源共享的问题呢? 所有解决多线程资源冲突问题的方法基本上都是采用给定时间只允许一个线程访问共享资源的方法,这时就需要给共享资源上一道锁。这就好比一个人上洗手间时,他进入洗手间后会将门锁上,出来时再将锁打开,然后其他人才可以进入。
1,同步块
Java 中提供了同步机制,可以有效地防止资源冲突。同步机制使用 synchronized 关键字,使用该关键字包含的代码块称为同步块,也称为临界区,语法如下:

synchronized (Object) {
}


通常将共享资源的操作放置在 synhronized 定义的区域内,这样当其他线程获取到这个锁时,就必须等待锁被释放后才可以进入该区域。Object 为任意一个对象,每个对象都存在一个标志位,并具有两个值,分别为 0和 1。一个线程运行到同步块时首先检查该对象的标志位,如果为0状态,表明此同步块内存在其他线程,这时当期线程处于就绪状态,直到处于同步块中的线程执行完同步块中的代码后,这时该对象的标识位设置为 1,当期线程才能开始执行同步块中的代码,并将 Object 对象的标识位设置为 0,以防止其他线程执行同步块中的代码。

例题7

package twentieth;public class SynchronizedTest implements Runnable {int num = 10; // 设置当前总票数public void run() {while (true) { // 设置无限循环synchronized (this) { // 设置同步代码块if (num > 0) { // 判断当前票数是否大于0try {Thread.sleep(100); // 使当前线程休眠100毫秒} catch (InterruptedException e) {e.printStackTrace();}// 票数减1System.out.println(Thread.currentThread().getName() + "——票数" + num--);}}}}public static void main(String[] args) {// 实例化类对象SynchronizedTest t = new SynchronizedTest();// 以该类对象分别实例化4个线程Thread tA = new Thread(t, "线程一");Thread tB = new Thread(t, "线程二");Thread tC = new Thread(t, "线程三");Thread tD = new Thread(t, "线程四");tA.start(); // 分别启动线程tB.start();tC.start();tD.start();}
}

同步方法


同步方法就是在方法前面用 synchronized 关键字修饰的方法,其语法如下:

synchronized void f(){
}


当某个对象调用了同步方法时,该对象上的其他同步方法必须等待该同步方法执行完毕后才能被执行。必须将每个能访问共享资源的方法修饰为 synchronized,否则就会出错修改例 20.7 的代码,将共享资源操作放置在一个同步方法中,代码如下:

int num = 10:
public synchronized void doit() {           //定义同步方法 
if(num>0){
try{
Thread.sleep(10);
}catch(InterruptedException eXe.printStackTrace();
票数"+num-);}
System.out.println(Thread.currentThread().getName()+"一
//在 run()方法中调用该同步方法
public void run()while(true)
doit();
}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/179017.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

怎么判断香港服务器的性能好不好?

随着互联网的不断发展&#xff0c;越来越多的人开始使用香港服务器来搭建自己的网站或者应用。但是&#xff0c;对于初次使用香港服务器的用户来说&#xff0c;往往会遇到一个问题&#xff1a;怎么判断香港服务器的性能好不好? 首先我们需要了解香港服务器的性能主要取决于哪些…

Vue CLI 初体验之如何创建一个项目并打开,以及组件的简单使用案例。

目录 什么是Vue CLI? 如何使用Vue CLI 创建一个项目 1.winr 打开cmd 输入vue create 1127(1127是文件名) 2.配置基础设置 选择Manually select features 选择Router和Vuex 选中vue版本&#xff08;我这里选vue3&#xff09; 剩下的看自己需要&#xff0c;如果不确定就一…

fiddler测试弱网别再去深山老林测了,这样做就能达到弱网效果了!

弱网测试 概念&#xff1a;弱网看字面意思就是网络比较弱&#xff0c;我们通称为信号差&#xff0c;网速慢。 意义&#xff1a;模拟在地铁、隧道、电梯和车库等场景下使用APP &#xff0c;网络会出现延时、中断和超时等情况。 添加图片注释&#xff0c;不超过 140 字&#xf…

C语言基础程序设计题

1.个人所得税计算 应纳税款的计算公式如下&#xff1a;收入<&#xff1d;1000元部分税率为0&#xff05;&#xff0c;2000元>&#xff1d;收入>1000元的部分税率为5&#xff05;&#xff0c;3000元>&#xff1d;收入>2000元的部分税率为10&#xff05;&#xf…

MySQL数据库入门到大牛_基础_18_MySQL8其它新特性(MySQL基础部分最后一章;新特性概述;窗口函数;公用表表达式)

文章目录 1. MySQL8新特性1.1 MySQL8.0 新增特性1.2 MySQL8.0移除的旧特性 2. 新特性1&#xff1a;窗口函数2.1 使用窗口函数前后对比2.2 窗口函数分类2.3 语法结构2.4 分类讲解1. 序号函数2. 分布函数3. 前后函数4. 首尾函数5. 其他函数 2.5 小 结 3. 新特性2&#xff1a;公用…

qt实现一个安卓测试小工具

qt实现一个安卓测试小工具 最终效果&#xff1a;目录结构源码gui.py 主要是按钮&#xff0c;文本控制代码main.py 主要是逻辑代码gui.spec 是打包使用的adb.ui 最终效果&#xff1a; 目录结构 上面2个是打包的生成的不用管 源码 gui.py 主要是按钮&#xff0c;文本控制代码…

借助工具落地提高外包软件项目代码提交规范

随着外包软件项目的不断增加&#xff0c;代码提交规范成为了一个必须解决的问题。由于外包项目的特殊性&#xff0c;很难保证每个开发者都按照统一的规范开发代码。为了解决这个问题&#xff0c;我们可以借助工具来提高代码提交规范。Codigger这个工具来解决外包软件项目中的代…

C++基础 -9- 函数的默认参数

函数默认格式(图片代码段呈现) #include "iostream"using namespace std;void rlxy(int a100) {cout << a << endl; }int main() {rlxy();rlxy(99); }函数默认参数注意事项 函数的默认参数从左开始推导 错误写法 正确写法

在微服务架构中的数据一致性

当从传统的单体应用架构转移到微服务架构时&#xff0c;特别是涉及数据一致性时&#xff0c;数据一致性是微服务架构中最困难的部分。传统的单体应用中&#xff0c;一个共享的关系型数据库负责处理数据一致性。在微服务架构中&#xff0c;如果使用“每个服务一个数据库”的模式…

【安卓】安卓xTS之Media模块 学习笔记(1) xTS介绍

1.背景 Media的安卓xTS相关测试和功能修复已经进行了一段时间了。 在此整理总结下xTS工作总结&#xff0c;留待后续查阅整理。 2. xTS介绍 - 什么是xTS 谷歌的xTS是对谷歌发布的CTS/GTS/VTS/STS/BTS/CTS-on-GSI等一系列测试的统称。 因为安卓系统比较庞大&#xff0c;模块多…

Microsoft Office Exce-筛选后的公式批量复制粘贴为值 并且不乱数据

Microsoft Office Exce-利用选择性粘贴将筛选后的公式结果批量转换为值 1、写好【客单价】公式&#xff0c;并下拉填充 &#xff08;【SKU】、【销售额】、【销售量】这三列都是常量&#xff0c;非公式&#xff09; 2、复制客单价公式到E列 3、筛选数据&#xff0c; 按 Delet…

Python基础语法之学习运算符

Python基础语法之学习运算符 一、代码二、效果 一、代码 print("1 1 ", 1 1) print("1 - 1 ", 1 - 1) print("1 * 1 ", 1 * 1) print("11 / 5 ", 11 / 5) print("11 // 5 ", 11 // 5) print("9 % 5 ", 9…

【C++ 程序设计入门基础】- 第3节-循环结构01

目录 循环结构 一、for 语句 for 循环案例 输入一个整数n&#xff0c;输出1&#xff5e;n的所有整数。 编译运行&#xff0c;查看输出结果 编译调试 for 循环结构语义分析 二、beak 语句 三、continue 语句 案例1&#xff1a; 案例2&#xff1a; 案例3&#xff1a; 循环…

ubuntu vmware开启3d加速画面异常

在ubuntu上开启vmware&#xff0c;进入全屏就会出现左上角和右下角两个不同的画面&#xff0c;并来回闪&#xff0c;不使用3d加速&#xff0c;一切正常&#xff0c;但是画面模糊。在ubuntu18 20 22上测试&#xff0c;vmware 15 16 17问题依旧。 原因 经过测试&#xff0c;原…

基于SpringBoot的手机官方商城系统

基于SpringBoot的手机官方商城系统 摘要&#xff1a;随着电子商务的发展&#xff0c;网上购物已成为人们普遍的购物方式。与此同时&#xff0c;网上支付也得到了迅速的发展&#xff0c;大有赶超传统支付的趋势。在今天这个信息化程度高、生活节奏快的现代社会&#xff0c;传统…

Java —— 泛型

目录 1. 什么是泛型 2. 泛型背景及其语法规则 3. 泛型类的使用 3.1 语法 3.2 示例 3.3 类型推导(Type Inference) 4. 裸类型(Raw Type) 4.1 说明 5. 泛型如何编译的 5.1 擦除机制 5.2 为什么不能实例化泛型类型数组 6. 泛型的上界 6.1 上界语法产生的背景 6.2 语法 6.3 示例 6.…

代码随想录算法训练营 ---第四十九天

前言&#xff1a; 今天是买卖股票的最佳时机系列&#xff0c;本系列之前在学习贪心思想时做过一些。 第一题&#xff1a; 简介&#xff1a; 本题在读题时我们要注意到几个细节 1.本题股票买卖只有一次。2.我们要在最低点买股票&#xff0c;在最高点卖股票。 我的思路&#…

【攻防世界-misc】hong

1.下载解压文件&#xff0c;是个音频文件&#xff0c;但打不开 2.复制到kali中先拆分看音频里面有隐含文件没有 用到的命令是&#xff1a;foremost 桌面/hong.mp3 点击桌面上的主文件夹 点击“output”文件夹&#xff0c; 点击文件中的jpg文件夹&#xff0c;有两张图片&#…

uniapp使用vue3和ts开发小程序获取用户城市定位

这个组件的功能&#xff1a;可以重新定位获取到用户的具体位置&#xff0c;这个是通过getLocation这个api和高德地图的api获取到的&#xff0c;getLocation这个api需要在微信公众平台后台>开发管理> 接口管理里面申请才能使用的&#xff0c;不然无法使用哦&#xff0c;这…

大数据存储技术期中考点梳理

1.CAP理论 分布式系统的CAP理论: 首先将分布式系统中的三个特性进行如下归纳: 口(一致性(C):在分布式系统中的所有数据备份&#xff0c;在同一时刻是否有同样的值。(等于所有节点访问同一份最新的数据副本) 口可用性(A):在集群中一部分节点故障后&#xff0c;集群整体是否还能…