09-java多线程

2023-11-19

多线程相关概念

并发和并行

  • 并行:在同一时刻,有多个指令在多个CPU上同时执行

  • 并发:在同一时刻,有多个指令在单个CPU上交替执行

进程和线程

  • 进程:是正在运行的程序

    • 独立性:进程是一个能独立运行的基本单位,同时也是系统分配资源和调度的独立单位
    • 动态性:进程的实质是程序的一次执行过程,进程是动态产生,动态消亡的
    • 并发性:任何进程都可以同其他进程一起并发执行
  • 线程:是进程中的单个顺序控制流,是一条执行路径

    • 单线程:一个进程如果只有一条执行路径,则称为单线程程序
    • 多线程:一个进程如果有多条执行路径,则称为多线程程序

多线程的创建

继承Thread类

  • 方法介绍

    方法名 说明
    void run() 在线程开启后,此方法将被调用执行
    void start() 使此线程开始执行,Java虚拟机会调用run方法()
  • 实现步骤

    1. 定义一个类MyThread继承Thread类,在MyThread类中重写run()方法
    2. 创建MyThread类的对象
    3. 启动线程
  • 代码演示

    public class MyThread extends Thread {
        @Override
        public void run() {
            for(int i=0; i<100; i++) {
                System.out.println(i);
            }
        }
    }
    public class MyThreadDemo {
        public static void main(String[] args) {
            MyThread my1 = new MyThread();
            MyThread my2 = new MyThread();
    
    //        my1.run();
    //        my2.run();
    
            //void start() 导致此线程开始执行; Java虚拟机调用此线程的run方法
            my1.start();
            my2.start();
        }
    }
    

实现Runnable接口

  • Thread构造方法

    方法名 说明
    Thread(Runnable target) 分配一个新的Thread对象
    Thread(Runnable target, String name) 分配一个新的Thread对象,并设置线程名
  • 实现步骤

    1. 定义一个类MyRunnable实现Runnable接口
    2. 在MyRunnable类中重写run()方法
    3. 创建MyRunnable类的对象
    4. 创建Thread类的对象,把MyRunnable对象作为构造方法的参数
    5. 启动线程
  • 代码演示

    package threadtest;
    
    public class MyRunnable implements Runnable {
        @Override
        public void run() {
            for (int i = 0; i < 10; i++) {
                System.out.println(Thread.currentThread().getName() + ":" + i);
            }
        }
    }
    
    class MyRunnableDemo {
        public static void main(String[] args) {
            //创建MyRunnable类的对象
            MyRunnable my = new MyRunnable();
    
            //创建Thread类的对象,把MyRunnable对象作为构造方法的参数
            //Thread(Runnable target)
    //        Thread t1 = new Thread(my);
    //        Thread t2 = new Thread(my);
    
            //Thread(Runnable target, String name)
            Thread t1 = new Thread(my, "坦克");
            Thread t2 = new Thread(my, "飞机");
    
            //启动线程
            t1.start();
            t2.start();
    
    
            // 另一种书写方式
            new Thread(new Runnable(){
                @Override
                public void run() {
                    System.out.println(Thread.currentThread().getName() + ":第二种书写方式" );
                }
            }).start();
        }
    }
    

实现Callable接口配合FutureTask

  • 方法介绍

    方法名 说明
    V call() 计算结果,如果无法计算结果,则抛出一个异常
    FutureTask(Callable< V > callable) 创建一个 FutureTask,一旦运行就执行给定的 Callable
    V get() 如有必要,等待计算完成,然后获取其结果
  • 实现步骤

    1. 定义一个类MyCallable实现Callable接口,在MyCallable类中重写call()方法
    2. 创建MyCallable类的对象
    3. 创建Future的实现类FutureTask对象,把MyCallable对象作为构造方法的参数
    4. 创建Thread类的对象,把FutureTask对象作为构造方法的参数
    5. 启动线程
    6. 再调用get方法,就可以获取线程结束之后的结果。
  • 代码演示

    public class MyCallable implements Callable<String> {
        @Override
        public String call() throws Exception {
            for (int i = 0; i < 100; i++) {
                System.out.println("跟女孩表白" + i);
            }
            //返回值就表示线程运行完毕之后的结果
            return "答应";
        }
    }
    public class Demo {
        public static void main(String[] args) throws ExecutionException, InterruptedException {
            //线程开启之后需要执行里面的call方法
            MyCallable mc = new MyCallable();
    
            //Thread t1 = new Thread(mc);
    
            //可以获取线程执行完毕之后的结果.也可以作为参数传递给Thread对象
            FutureTask<String> ft = new FutureTask<>(mc);
    
            //创建线程对象
            Thread t1 = new Thread(ft);
    
            String s = ft.get();
            //开启线程
            t1.start();
    
            //String s = ft.get();
            System.out.println(s);
        }
    }
    

创建线程三种实现方式的对比

方式 优点 缺点
继承Thread接口 编程比较简单,可以直接使用Thread类中的方法 可以扩展性较差,不能再继承其他的类
实现Runnable接口 扩展性强,可以继续继承和实现其他的类 不能返回线程执行的结果
实现Callable接口配合FutureTask 扩展性强,可以继续继承和实现其他的类。可以得到线程执行的结果 编程相对复杂

Thread的常用方法

方法名称 说明
String getName() 获取当前线程名称,默认线程名称时Thread-索引
void setName() 设置线程名称
public static Thread currentThread() 获取当前正在执行的线程对象
public static void sleep() 使当前正在执行的线程停留(暂停执行)指定的毫秒数
public void run() 线程任务方法,用来封装被线程执行的代码,直接访问相当于普通方法
public void start() 线程启动方法,然后由JVM调用此线程的run()方法

设置和获取线程名称

  • 代码演示

    public class MyThread extends Thread {
        public MyThread() {}
        public MyThread(String name) {
            super(name);
        }
    
        @Override
        public void run() {
            for (int i = 0; i < 100; i++) {
                System.out.println(getName()+":"+i);
            }
        }
    }
    public class MyThreadDemo {
        public static void main(String[] args) {
            MyThread my1 = new MyThread();
            MyThread my2 = new MyThread();
    
            //void setName(String name):将此线程的名称更改为等于参数 name
            my1.setName("高铁");
            my2.setName("飞机");
    
            //Thread(String name)
            MyThread my1 = new MyThread("高铁");
            MyThread my2 = new MyThread("飞机");
    
            my1.start();
            my2.start();
    
            //static Thread currentThread() 返回对当前正在执行的线程对象的引用
            System.out.println(Thread.currentThread().getName());
        }
    }
    

线程休眠

  • 代码演示

    public class MyRunnable implements Runnable {
        @Override
        public void run() {
            for (int i = 0; i < 100; i++) {
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
    
                System.out.println(Thread.currentThread().getName() + "---" + i);
            }
        }
    }
    public class Demo {
        public static void main(String[] args) throws InterruptedException {
            /*System.out.println("睡觉前");
            Thread.sleep(3000);
            System.out.println("睡醒了");*/
    
            MyRunnable mr = new MyRunnable();
    
            Thread t1 = new Thread(mr);
            Thread t2 = new Thread(mr);
    
            t1.start();
            t2.start();
        }
    }
    

线程安全、线程同步

线程安全

  • 多个线程同时操作一个共享资源资源的时候可能会出现业务安全问题,称为线程安全问题

线程同步

  • 为了解决线程安全的问题

线程同步的核心思想

  • 加锁,把共享资源上锁,每次只能让一个线程进入访问,访问完毕之后解锁,然后其他线程才能进来

线程同步的方式

  • 同步代码块
  • 同步方法
  • 同步锁

案例-卖票

  • 案例需求

    某电影院目前正在上映国产大片,共有100张票,而它有3个窗口卖票,请设计一个程序模拟该电影院卖票

  • 实现步骤

    • 定义一个类SellTicket实现Runnable接口,里面定义一个成员变量:private int tickets = 100;在SellTicket类中重写run()方法实现卖票,代码步骤如下

    • 判断票数大于0,就卖票,并告知是哪个窗口卖的

    • 卖了票之后,总票数要减1

    • 票卖没了,线程停止

    • 定义一个测试类SellTicketDemo,里面有main方法,代码步骤如下

    • 创建SellTicket类的对象

    • 创建三个Thread类的对象,把SellTicket对象作为构造方法的参数,并给出对应的窗口名称

    • 启动线程

  • 代码实现

    public class SellTicket implements Runnable {
        private int tickets = 100;
        //在SellTicket类中重写run()方法实现卖票,代码步骤如下
        @Override
        public void run() {
            while (true) {
                if(ticket <= 0){
                        //卖完了
                        break;
                    }else{
                        try {
                            Thread.sleep(100);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        ticket--;
                        System.out.println(Thread.currentThread().getName() + "在卖票,还剩下" + ticket + "张票");
                    }
            }
        }
    }
    public class SellTicketDemo {
        public static void main(String[] args) {
            //创建SellTicket类的对象
            SellTicket st = new SellTicket();
    
            //创建三个Thread类的对象,把SellTicket对象作为构造方法的参数,并给出对应的窗口名称
            Thread t1 = new Thread(st,"窗口1");
            Thread t2 = new Thread(st,"窗口2");
            Thread t3 = new Thread(st,"窗口3");
    
            //启动线程
            t1.start();
            t2.start();
            t3.start();
        }
    }
    

卖票案例的问题

  • 卖票出现了问题

    • 相同的票出现了多次

    • 出现了负数的票

  • 问题产生原因

    线程执行的随机性导致的,可能在卖票过程中丢失cpu的执行权,导致出现问题

解决线程安全-同步代码块

  • 安全问题出现的条件

    • 是多线程环境

    • 有共享数据

    • 有多条语句操作共享数据

  • 如何解决多线程安全问题呢?

    • 基本思想:让程序没有安全问题的环境
  • 怎么实现呢?

    • 把多条语句操作共享数据的代码给锁起来,让任意时刻只能有一个线程执行即可

    • Java提供了同步代码块的方式来解决

  • 同步代码块格式:

    synchronized(任意对象) { 
    	多条语句操作共享数据的代码 
    }
    
    

    synchronized(任意对象):就相当于给代码加锁了,任意对象就可以看成是一把锁

  • 同步的好处和弊端

    • 好处:解决了多线程的数据安全问题

    • 弊端:当线程很多时,因为每个线程都会去判断同步上的锁,这是很耗费资源的,无形中会降低程序的运行效率

  • 代码演示

    public class SellTicket implements Runnable {
        private int tickets = 100;
        private Object obj = new Object();
    
        @Override
        public void run() {
            while (true) {
                synchronized (obj) { // 对可能有安全问题的代码加锁,多个线程必须使用同一把锁
                    //t1进来后,就会把这段代码给锁起来
                    if (tickets > 0) {
                        try {
                            Thread.sleep(100);
                            //t1休息100毫秒
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        //窗口1正在出售第100张票
                        System.out.println(Thread.currentThread().getName() + "正在出售第" + tickets + "张票");
                        tickets--; //tickets = 99;
                    }
                }
                //t1出来了,这段代码的锁就被释放了
            }
        }
    }
    
    public class SellTicketDemo {
        public static void main(String[] args) {
            SellTicket st = new SellTicket();
    
            Thread t1 = new Thread(st, "窗口1");
            Thread t2 = new Thread(st, "窗口2");
            Thread t3 = new Thread(st, "窗口3");
    
            t1.start();
            t2.start();
            t3.start();
        }
    }
    
    

解决线程安全-同步方法

  • 同步方法的格式

    同步方法:就是把synchronized关键字加到方法上

    修饰符 synchronized 返回值类型 方法名(方法参数) { 
    	方法体;
    }
    

    同步方法的锁对象是什么呢?

    this

  • 静态同步方法

    同步静态方法:就是把synchronized关键字加到静态方法上

    修饰符 static synchronized 返回值类型 方法名(方法参数) { 
    	方法体;
    }
    

    同步静态方法的锁对象是什么呢?

    类名.class

  • 代码演示

    public class MyRunnable implements Runnable {
        private static int ticketCount = 100;
    
        @Override
        public void run() {
            while(true){
                if("窗口一".equals(Thread.currentThread().getName())){
                    //同步方法
                    boolean result = synchronizedMthod();
                    if(result){
                        break;
                    }
                }
    
                if("窗口二".equals(Thread.currentThread().getName())){
                    //同步代码块
                    synchronized (MyRunnable.class){
                        if(ticketCount == 0){
                           break;
                        }else{
                            try {
                                Thread.sleep(10);
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                            ticketCount--;
                            System.out.println(Thread.currentThread().getName() + "在卖票,还剩下" + ticketCount + "张票");
                        }
                    }
                }
    
            }
        }
    
        private static synchronized boolean synchronizedMthod() {
            if(ticketCount == 0){
                return true;
            }else{
                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                ticketCount--;
                System.out.println(Thread.currentThread().getName() + "在卖票,还剩下" + ticketCount + "张票");
                return false;
            }
        }
    }
    
    
    class Demo {
      public static void main(String[] args) {
          MyRunnable mr = new MyRunnable();
          Thread t1 = new Thread(mr);
          Thread t2 = new Thread(mr);
      
          t1.setName("窗口一");
          t2.setName("窗口二");
      
          t1.start();
            t2.start();
        }
    

    }

解决线程安全-Lock锁

虽然我们可以理解同步代码块和同步方法的锁对象问题,但是我们并没有直接看到在哪里加上了锁,在哪里释放了锁,为了更清晰的表达如何加锁和释放锁,JDK5以后提供了一个新的锁对象Lock

Lock是接口不能直接实例化,这里采用它的实现类ReentrantLock来实例化

  • ReentrantLock构造方法

    方法名 说明
    ReentrantLock() 创建一个ReentrantLock的实例
  • 加锁解锁方法

    方法名 说明
    void lock() 获得锁
    void unlock() 释放锁
  • 代码演示

    public class Ticket implements Runnable {
        //票的数量
        private int ticket = 100;
        private Object obj = new Object();
        private final ReentrantLock lock = new ReentrantLock();
    
        @Override
        public void run() {
            while (true) {
                //synchronized (obj){//多个线程必须使用同一把锁.
                try {
                    lock.lock();
                    if (ticket <= 0) {
                        //卖完了
                        break;
                    } else {
                        Thread.sleep(100);
                        ticket--;
                        System.out.println(Thread.currentThread().getName() + "在卖票,还剩下" + ticket + "张票");
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    lock.unlock();
                }
                // }
            }
        }
    }
    
    public class Demo {
        public static void main(String[] args) {
            Ticket ticket = new Ticket();
    
            Thread t1 = new Thread(ticket);
            Thread t2 = new Thread(ticket);
            Thread t3 = new Thread(ticket);
    
            t1.setName("窗口一");
            t2.setName("窗口二");
            t3.setName("窗口三");
    
            t1.start();
            t2.start();
            t3.start();
        }
    }
    

死锁

  • 概述

    线程死锁是指由于两个或者多个线程互相持有对方所需要的资源,导致这些线程处于等待状态,无法前往执行

  • 什么情况下会产生死锁

    1. 资源有限
    2. 同步嵌套
  • 代码演示

    public class Demo {
        public static void main(String[] args) {
            Object objA = new Object();
            Object objB = new Object();
    
            new Thread(()->{
                while(true){
                    synchronized (objA){
                        //线程一
                        synchronized (objB){
                            System.out.println("小康同学正在走路");
                        }
                    }
                }
            }).start();
    
            new Thread(()->{
                while(true){
                    synchronized (objB){
                        //线程二
                        synchronized (objA){
                            System.out.println("小薇同学正在走路");
                        }
                    }
                }
            }).start();
        }
    }
    
    

线程通信

线程池

定时器

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

09-java多线程 的相关文章

  • 如何为最终用户方便地启动Java GUI程序

    用户想要从以下位置启动 Java GUI 应用程序Windows 以及一些额外的 JVM 参数 例如 javaw Djava util logging config file logging properties jar MyGUI jar
  • 如何使用 Java 和 Selenium WebDriver 在 C 目录中创建文件夹并需要将屏幕截图保存在该目录中?

    目前正在与硒网络驱动程序和代码Java 我有一种情况 我需要在 C 目录中创建一个文件夹 并在该文件夹中创建我通过 selenium Web 驱动程序代码拍摄的屏幕截图 它需要存储在带有时间戳的文件夹中 如果我每天按计划运行脚本 所有屏幕截
  • 在画布上绘图

    我正在编写一个 Android 应用程序 它可以在视图的 onDraw 事件上直接绘制到画布上 我正在绘制一些涉及单独绘制每个像素的东西 为此我使用类似的东西 for int x 0 x lt xMax x for int y 0 y lt
  • 使用 Android 发送 HTTP Post 请求

    我一直在尝试从 SO 和其他网站上的大量示例中学习 但我无法弄清楚为什么我编写的示例不起作用 我正在构建一个小型概念验证应用程序 它可以识别语音并将其 文本 作为 POST 请求发送到 node js 服务器 我已确认语音识别有效 并且服务
  • INSERT..RETURNING 在 JOOQ 中不起作用

    我有一个 MariaDB 数据库 我正在尝试在表中插入一行users 它有一个生成的id我想在插入后得到它 我见过this http www jooq org doc 3 8 manual sql building sql statemen
  • 无法展开 RemoteViews - 错误通知

    最近 我收到越来越多的用户收到 RemoteServiceException 错误的报告 我每次给出的堆栈跟踪如下 android app RemoteServiceException Bad notification posted fro
  • 多个 Maven 配置文件激活多个 Spring 配置文件

    我想在 Maven 中构建一个环境 在其中我想根据哪些 Maven 配置文件处于活动状态来累积激活多个 spring 配置文件 目前我的 pom xml 的相关部分如下所示
  • 反射找不到对象子类型

    我试图通过使用反射来获取包中的所有类 当我使用具体类的代码 本例中为 A 时 它可以工作并打印子类信息 B 扩展 A 因此它打印 B 信息 但是当我将它与对象类一起使用时 它不起作用 我该如何修复它 这段代码的工作原理 Reflection
  • 路径中 File.separator 和斜杠之间的区别

    使用有什么区别File separator和一个正常的 在 Java 路径字符串中 与双反斜杠相反 平台独立性似乎不是原因 因为两个版本都可以在 Windows 和 Unix 下运行 public class SlashTest Test
  • 十进制到八进制的转换[重复]

    这个问题在这里已经有答案了 可能的重复 十进制转换错误 https stackoverflow com questions 13142977 decimal conversion error 我正在为一个类编写一个程序 并且在计算如何将八进
  • Java TestNG 与跨多个测试的数据驱动测试

    我正在电子商务平台中测试一系列商店 每个商店都有一系列属性 我正在考虑对其进行自动化测试 是否有可能有一个数据提供者在整个测试套件中提供数据 而不仅仅是 TestNG 中的测试 我尝试不使用 testNG xml 文件作为机制 因为这些属性
  • 在两个活动之间传输数据[重复]

    这个问题在这里已经有答案了 我正在尝试在两个不同的活动之间发送和接收数据 我在这个网站上看到了一些其他问题 但没有任何问题涉及保留头等舱的状态 例如 如果我想从 A 类发送一个整数 X 到 B 类 然后对整数 X 进行一些操作 然后将其发送
  • 加密 JBoss 配置中的敏感信息

    JBoss 中的标准数据源配置要求数据库用户的用户名和密码位于 xxx ds xml 文件中 如果我将数据源定义为 c3p0 mbean 我会遇到同样的问题 是否有标准方法来加密用户和密码 保存密钥的好地方是什么 这当然也与 tomcat
  • Java Integer CompareTo() - 为什么使用比较与减法?

    我发现java lang Integer实施compareTo方法如下 public int compareTo Integer anotherInteger int thisVal this value int anotherVal an
  • Google App Engine 如何预编译 Java?

    App Engine 对应用程序的 Java 字节码使用 预编译 过程 以增强应用程序在 Java 运行时环境中的性能 预编译代码的功能与原始字节码相同 有没有详细的信息这是做什么的 我在一个中找到了这个谷歌群组消息 http groups
  • simpleframework,将空元素反序列化为空字符串而不是 null

    我使用简单框架 http simple sourceforge net http simple sourceforge net 在一个项目中满足我的序列化 反序列化需求 但在处理空 空字符串值时它不能按预期工作 好吧 至少不是我所期望的 如
  • 获取 JVM 上所有引导类的列表?

    有一种方法叫做findBootstrapClass对于一个类加载器 如果它是引导的 则返回一个类 有没有办法找到类已经加载了 您可以尝试首先通过例如获取引导类加载器呼叫 ClassLoader bootstrapLoader ClassLo
  • 使用 JMF 创建 RTP 流时出现问题

    我正处于一个项目的早期阶段 需要使用 RTP 广播DataStream创建自MediaLocation 我正在遵循一些示例代码 该代码目前在rptManager initalize localAddress 出现错误 无法打开本地数据端口
  • 如何实现仅当可用内存较低时才将数据交换到磁盘的写缓存

    我想将应用程序生成的数据缓存在内存中 但如果内存变得稀缺 我想将数据交换到磁盘 理想情况下 我希望虚拟机通知它需要内存并将我的数据写入磁盘并以这种方式释放一些内存 但我没有看到任何方法以通知我的方式将自己挂接到虚拟机中before an O
  • 使用 xpath 和 vtd-xml 以字符串形式获取元素的子节点和文本

    这是我的 XML 的一部分

随机推荐

  • 【ReactiveX】Observable 对象(译)

    更多内容 欢迎关注作者博客 http www china10s com blog p 475 Observable 对象 在 ReactiveX 中 一个观察者向 Observable 对象订阅消息 然后这个观察者将会响应 Observab
  • 区块链学习笔记4——BTC实现

    区块链学习笔记4 BTC实现 学习视频 北京大学肖臻老师 区块链技术与应用 笔记参考 北京大学肖臻老师 区块链技术与应用 公开课系列笔记 目录导航页 UTXO 区块链是一个去中心化的账本 比特币采用了基于交易的账本模式 然而 系统中并没有记
  • IPv4、IPv6、UDP、TCP数据报首部格式分析

    一 IPv4首部格式 图片来源 图解TCP IP 通过wireshark抓QQ的数据报 IPV4的数据报格式和上面的一致 现在进行分析 相对重要的会红色标记 1 版本 version 由4比特构成 表示标识IP首部的版本号 如上是版本号为4
  • 面试专题:Linux运维精华面试题

    下面是一名资深Linux运维求职数十家公司总结的Linux运维面试精华 助力大家跳槽找个高薪好工作 1 什么是运维 什么是游戏运维 1 运维是指大型组织已经建立好的网络软硬件的维护 就是要保证业务的上线与运作的正常 在他运转的过程中 对他进
  • java双人对弈五子棋源码_java swing 双人五子棋源代码

    import java awt Color import java awt Font import java awt Graphics import java awt Toolkit import java awt event MouseE
  • C++ 类中的static成员的初始化和特点

    C 类中的static成员的初始化和特点 在C 的类中有些成员变量初始化和一般数据类型的成员变量有所不同 以下测试编译环境为 g v Using built in specs COLLECT GCC g Target x86 64 linu
  • 删除排序数组的重复项(给定一个排序数组,你需要在原地删除重复出现的元素,使得每个元素只出现一次,返回移除后数组的新长度。不要使用额外的数组空间)

    给定一个排序数组 你需要在原地删除重复出现的元素 使得每个元素只出现一次 返回移除后数组的新长度 不要使用额外的数组空间 你必须在原地修改输入数组并在使用 O 1 额外空间的条件下完成 示例 1 给定数组 nums 1 1 2 函数应该返回
  • 第八章 聊聊区块链的几个数字

    第八章 聊聊区块链的几个数字 1 概述 2 2100W 3 每个区块10分钟 4 挖矿奖励4年递减1次 5 区块确认6次永久生效 6 51 算力攻击 6 1 币安黑客事件 参考资料 1 概述 在学习区块链过程中 会发现一些数字 心里不断问自
  • 使用MVC框架简单搭建一个数据库-后台-服务器Web项目

    在对Tomcat技术基本了解之后 用MVC框架简单搭建一个数据库 后台 服务器Web项目 MVC框架简介 MVC 是一种使用 MVC Model View Controller 模型 视图 控制器 设计创建 Web 应用程序的模式 Mode
  • 安全之公开密钥基本知识

    文件加密的基本知识 1 公开密钥密码 传统密码的缺点 1 收发双方持有相同密钥 密钥分配困难 KE KD K E K D 2 不能方便的实现数字签名 应用不方便 数字签名概念下面有 历史 公开密钥密码又称为双钥密码或非对称密码 是1976年
  • 企业网站建设方案书

    一 网站建设目标 1 1背景分析 现在网络的发展已呈现商业化 全民化 全球化的趋势 目前 几乎世界上所有的公司都在利用网络传递商业信息 进行商业活动 从宣传企业 发布广告 招聘雇员 传递商业文件乃至拓展市场 网上销售等 无所不能 如今网络已
  • iPhone Safari下iframe不显示滚动条无法滚动的解决方法

    div class dataTables wrapper style height 300px div
  • Go渗透测试笔记(二)---TCP,扫描器和代理

    Go渗透测试笔记 二 TCP 扫描器和代理 0x00 前言 TCP是面向连接协议的主要标准 也是现代网络的基础 作为攻击者 我们应当了解TCP的工作原理 并且能够开发可用的TCP结构体 以便可以识别 打开 关闭 的端口 找出错误的结果 如误
  • TCP/IP协议栈及网络基础,协议栈原理及实现

    1 TCP IP协议栈及网络基础 推荐这个在B站几千观看的视频讲解 底层原理到徒手实现 TCP IP网络协议栈 tcp协议栈 如何实现 C C Linux服务器开发高级架构学习视频点击 C C Linux服务器开发高级架构师 Linux后台
  • 正则表达式工具类

    在实际开发中总会使用到正则表达式匹配数据 我也是在后面查看了一些资料 下面写一个常用的正则表达式匹配集合 正则匹配模式 表示匹配字符串的开始位置 例外 用在中括号中 时 可以理解为取反 表示不匹配括号中字符串 表示匹配字符串的结束位置 表示
  • 量化交易动了谁的奶酪

    最近关于量化交易的政策讨论频出 在内容上 主要是限制其高频交易和某些可能对市场产生负面影响的行为 具体来说 中国证券监督管理委员会和上海证券交易所等机构都出台了相关政策 对量化交易的频率 规模 风险控制等方面进行了限制 这些政策的出台主要是
  • python--模块导入

    目录 模块简介 模块导入的两种方式 方式一 import 方式二 from import 模块简介 1 什么是模块 模块就是一系列功能的结合体 可以直接使用 2 为什么要用模块 极大地提升开发效率 拿来主义 gt gt gt 站在巨人的肩膀
  • docker部署redis集群实现动态扩缩容

    目录 思考 分布式存储的解决方案 哈希取余分区 一致性哈希算法分区 哈希槽分区 采用哈希槽分区 部署三主三从 docker 准备工作 创建3主3从redis实例 进入容器中 构建主从关系 主从容错切换迁移 主从扩容 主从缩容 思考 假如现有
  • canvas实战之酷炫背景动画(一)

    系列文章 canvas实战之酷炫背景动画 一 canvas实战之酷炫背景动画 二 canvas实战之酷炫背景动画 三 canvas实战之酷炫背景动画 四 canvas实战之酷炫背景动画 五 canvas实战之酷炫背景动画 六 canvas实
  • 09-java多线程

    多线程相关概念 并发和并行 并行 在同一时刻 有多个指令在多个CPU上同时执行 并发 在同一时刻 有多个指令在单个CPU上交替执行 进程和线程 进程 是正在运行的程序 独立性 进程是一个能独立运行的基本单位 同时也是系统分配资源和调度的独立