大数据——Java多线程

2023-10-26

认识线程

计算机的操作系统多采用多任务和分时设计,多任务是指在一个操作系统中可以同时运行多个程序,例如,可以在使用QQ聊天的同时听音乐,既有多个独立运行的任务,每个任务对应一个进程,每个进程又可产生多个线程。

进程

认识进程先从程序开始。程序是对数据描述与操作的代码的集合,如Office中的Word、暴风影音等应用程序。
进程是程序的一次动态执行过程,它对应了从代码加载、执行至执行完毕的一个完整过程,这个过程也是进程本身从产生、发展至消亡的过程。操作系统同时管理一个计算机系统中的多个进程,让计算机系统中的多个进程轮流使用CPU资源,或者共享操作系统的其他资源。
进程有如下特点:
进程是系统运行程序的基本单位。
每一个进程都有自己独立的一块内存空间、一组系统资源。
每一个进程的内部数据和状态都是完全独立的。

线程

线程是进程中执行运算的最小单位,-一个进程在其执行过程中可以产生多个线程,而线程必须在某个进程内执行。
线程是进程内部的一个执行单元, 是可完成一个独 立任务的顺序控制流程, 如果在一个进程中同时运行了多个线程,用来完成不同的工作,则称之为多线程。
线程按处理级别可以分为核心级线程和用户级线程。
(1)核心级线程
核心级线程是和系统任务相关的线程,它负责处理不同进程之间的多个线程。允许不同进程中的线程按照同一相对优先调度方法对线程进行调度,使它们有条不紊地工作,可以发挥多处理器的并发优势,以充分利用计算机的软/硬件资源。
(2)用户级线程
在开发程序时,由于程序的需要而编写的线程即用户级线程,这些线程的创建、执行和消亡都是在编写应用程序时进行控制的。对于用户级线程的切换,通常发生在一一个应用程序的诸多线程之间,如迅雷中的多线程下载就属于用户线程。
多线程可以改善用户体验。具有多个线程的进程能更好地表达和解决现实世界的具体问题,多线程是计算机应用开发和程序设计的一项重要的实用技术。
线程和进程既有联系又有区别,具体如下:
①一个进程中至少要有一个线程。
②资源分配给进程,同一进程的所有线程共享该进程的所有资源。
③处理机分配给线程,即真正在处理机上运行的是线程。

多线程的优势

多线程有着广泛的应用,下载工具“迅雷”是一款典型的多线程应用程序,在这个下载工具中,可以同时执行多个下载任务。这样不但能够加快下载的速度,减少等待时间,而且还能够充分利用网络和系统资源。
多线程的好处如下:
①多线程程序可以带来更好的用户体验,避免因程序执行过慢而导致出现计算机死机或者白屏的情况。
②多线程程序可以最大限度地提高计算机系统的利用效率,如迅雷的多线程下载。

编写线程类

每个程序至少自动拥有一个线程,称为主线程。当程序加载到内存时启动主线程。Java程序中的public static void main()方法是主线程的入口,运行Java程序时,会先执行这个方法。
开发中,用户编写的线程一般都是指除了主线程之外的其他线程。
使用一个线程的过程可以分为如下4个步骤:
(1)定义一一个线程,同时指明这个线程所要执行的代码,即期望完成的功能。
(2)创建线程对象。
(3)启动线程。
(4)终止线程。
定义一个线程类通常有两种方法,分别是继承java.lang.Thread类和实现java.lang.Runnable接口。

使用Thread类创建线程。

Java提供了java.lang.Thread类支持多线程编程,该类提供了大量的方法来控制和操作线程,常用方法如下所示:

方法 说明
void run() 执行任务操作的方法
void start() 使该线程开始执行
void sleep(long millis) 在指定的毫秒数内让当前正在执行的线程休眠(暂停执行)
String getName() 返回该线程的名称
int getPriority() 返回线程的优先级
void setPriority(int newPriority) 更改线程的优先级
Thread.State getState() 返回该线程的状态
boolean isAlive() 测试线程是否处于活动状态
void join() 等待该线程终止
void interrupt() 中断线程
void yield() 暂停当前正在执行的线程对象,并执行其他线程

创建线程时继承Thread类并重写Thread类的run()方法。Thread类的run()方法是线程要执行操作任务的方法,所以线程要执行的操作代码都需要写在run()方法中,并通过调用start()方法来启动线程。
示例一:创建两个子线程,每个线程均输出20次消息数字、“你好”、线程名。
代码展示:

// An highlighted block
public class test2 extends Thread {
    @Override
    public void run() {
        for (int i = 1; i <= 20; i++) {
            System.out.println(i+".你好,来自线程"+Thread.currentThread().getName());
        }
    }
    public static void main(String[] args) {
        test2 t = new test2();
        Thread t1 = new Thread(t);
        Thread t2 = new Thread(t);
        t1.start();
        t2.start();
    }
}

输出结果:在这里插入图片描述

使用Runnable接口创建线程

使用继承Thread类的方式创建线程简单明了,符合大家的习惯。但它也有个缺点,如果定义的类已经继承了其他类则无法再继承Thread类。使用Runnable接口创建线程的方式可以解决问题。
Runnable接口中声明了一个run()方法,即public void run()。一个类可以通过实现Runnable接口并实现其run()方法完成线程的所有活动,已实现的run()方法称为该对象的线程体。任何实现Runnable接口的对象都可以作为一个线程的目标对象。
示例二:修改示例一,要求线程类使用实现Runnable接口的方式创建。
代码展示:

public class test1 implements Runnable{
    @Override
    public void run() {
        for (int i = 1; i <=20 ; i++) {
            System.out.println(i+".你好,来自线程"+Thread.currentThread().getName());
        }
    }
    public static void main(String[] args) {
        test1 t = new test1();
        Thread t1 = new Thread(t);
        Thread t2 = new Thread(t);
        t1.start();
        t2.start();
    }
}

输出结果:在这里插入图片描述
两种创建线程的方式有各自的特点和应用领域:直接继承Thread类的方式编写简单,可以直接操作线程,适用于单重继承;实现Runnable接口的方式,当一个线程继承了另一个类时,就只能实现Runnable接口的方法来创建线程,而且这种方法还可以使多个线程之间使用同一个Runnable对象。

使用Callable接口创建线程

Callable接口的用法跟Runnable接口的用法大致相似。
示例三:

import java.util.concurrent.*;
public class TestCallable implements Callable<Integer> {
    @Override
    public Integer call()throws Exception {
        for (int i = 0; i < 10; i++) {
            System.out.println(Thread.currentThread().getName() + ":" + (i + 1));
        }
        return 3;
    }

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        TestCallable t=new TestCallable();
        FutureTask<Integer> f = new FutureTask<Integer>(t);
        Thread th = new Thread(f);
        th.start();
        Integer a = f.get();
        System.out.println(a);
        //线程池
//        ExecutorService single = Executors.newSingleThreadExecutor();
//        ExecutorService executorService = Executors.newFixedThreadPool(3);
    }
}

输出结果:在这里插入图片描述

线程的状态

线程的生命周期可以分为4个阶段,即线程的4中状态,分别为新生状态、可运行状态、阻塞状态和死亡状态。
一个具有生命的线程,总是处于这4种状态。线程的生命周期如下所示:
在这里插入图片描述

新生状态(New Thread)

创建线程对象之后,尚未调用其start()方法之前,这个线程就有了生命,此时线程仅仅是一个空对象,系统没有为其分配资源。此时只能启动和终止线程,任何其他操作都会引发异常。

可运行状态(Runnable)

当调用start()方法启动线程之后,系统为该线程分配除CPU外的所需资源,这个线程就有了运行的机会,线程处于可运行的状态,在这个状态当中,该线程对象可能正在运行,也可能尚未运行。对于只有一个CPU的机器而言,任何时刻只能有一个处于可运行状态的线程占用处理机,获得CPU资源,此时系统真正运行线程的run()方法。

阻塞状态(Blocked)

一个正在运行的线程因某种原因不能继续运行时,进入阻塞状态。阻塞状态是一种“不可运行”的状态,而处于这种状态的线程在得到一个特定的事件之后会转回可运行状态。
导致一个线程被阻塞有以下原因:
(1)调用了Thread类的静态方法sleep()。
(2)一个线程执行到一个I/O操作时,如果I/O操作尚未完成,则线程将被阻塞。
(3)如果一个线程的执行需要得到一个对象的锁,而这个对象的锁正被别的线程占用,那么此线程会被阻塞。
(4)线程的suspend()方法被调用而使线程被挂起时,线程进入阻塞状态。但suspend()容易导致死锁,已经被JDK列为过期方法,基本不再使用。
处于阻塞状态的线程可以转回可运行状态,例如,在调用sleep()方法之后,这个线程的睡眠时间已经达到了指定的间隔,那么它就有可能重新回到可运行状态,或当一个线程等待的锁变得可用的时候,那么这个线程也会从被阻塞状态转入可运行状态。

死亡状态(Dead)

一个线程的run()方法运行完毕、stop()方法被调用或者在运行过程中出现未捕获的异常时,线程进入死亡状态。

线程调度

当同一时刻有多个线程处于可运行状态,它们需要排队等待CPU资源,每个线程会自动获得一个线程的优先级(Priority),优先级的高低反映线程的重要或紧急程度。可运行状态的线程按优先级排队,线程调度依据建立在优先级基础上的“先到先服务”原则。
线程调度管理器负责线程排队和在线程间分配CPU,并按线程调度算法进行调度。当线程调度管理器选中某个线程时,该线程获得CPU资源进入运行状态。
线程调度是抢占式调度,即在当前线程执行过程中如果有一个更高优先级的线程进入可运行状态,则这个更高优先级的线程立即被调度执行。

线程优先级

线程的优先级用1~10表示,10表示优先级最高,默认值是5,。每个优先级对应一个Thread类的公用静态常量
线程的优先级可以通过setPriority(int grade)方法更改,此方法的参数表示要设置的优先级,它必须是1~10的整数。

实现线程调度的方法

join()方法

join()方法使当前线程暂停,等待调用该方法的线程结束后再继续执行本线程。它有三种重载形式。
public final void join();
public final void join(long mills);
public final void join(long mills,int nanos)
示例四:使用join()方法阻塞线程。
实现步骤如下:
(1)定义线程类,输出5次当前线程的名称。
(2)定义测试类,使用join()方法阻塞主线程。
代码展示:

public class MyThread extends Thread {
    public MyThread(String name) {
        super(name);
    }

    @Override
    public void run() {
        for (int i = 0; i < 5; i++) {
            //输出当前线程的名称
            System.out.println(Thread.currentThread().getName() + "" + i);
        }
    }

    public static void main(String[] args) {
        for (int i = 0; i < 10; i++) {
            if (i == 5) {//主线程运行5次后,开始MyThread线程
                MyThread tempjt = new MyThread("MyThread");
                try {
                    tempjt.start();
                    tempjt.join();//把该线程通过join()方法插入到主线程前面
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println(Thread.currentThread().getName()+""+i);
        }
    }
}

输出结果:
在这里插入图片描述
在示例三中,使用join()方法阻塞指定的线程直到另一个线程完成以后再继续执行,其中tempjt.join();表示让当前线程即主线程加到tempjt的末尾,主线程被阻塞,tempjt执行完以后主线程才能继续执行。Thread.currentThread().getName()用于获取当前线程的名称。
从线程 返回数据时也经常使用到join()方法。

sleep()方法

sleep()方法的语法格式如下:
public static void sleep(long millis);
sleep()方法会让当前线程睡眠(停止执行)millis毫秒,线程由运行中的状态进入不可运行状态,睡眠时间过后线程会再次进入可运行状态。
示例五:使用sleep()方法阻塞线程。
实现步骤如下:
(1)定义线程。
(2)在run()方法中使用sleep()方法阻塞线程。
(3)定义测试类。
代码展示:

public class Wait {
    public static void bySec(long s) {
        for (int i = 0; i < s; i++) {
            System.out.println((i + 1) + "秒");
            try {
                Thread.sleep(1000);//睡眠1秒
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        }
    }

    public static void main(String[] args) {
        System.out.println("Wait");//提示等待
        Wait.bySec(5);//让主线程等待5秒再执行
        System.out.println("start");//提示恢复执行
    }
}

输出结果:
在这里插入图片描述

yield()方法

yield()方法的语法格式如下:
public static void yield()
yield()方法可让当前线程暂停执行,允许其他线程执行,但该线程仍处于可运行状态,并不变为阻塞状态。此时,系统选择其他相同或更高优先级线程执行,若无其他相同或更高优先级线程,则该线程继续执行。
示例六:使用yield()方法暂停线程。
实现步骤如下:
(1)定义两个线程。
(2)在run()方法中使用yield()方法暂停线程。
(3)定义测试类。
代码展示:

public class FirstThread extends Thread {
    @Override
    public void run() {
        for (int i = 0; i < 5; i++) {
            System.out.println("第一个线程的第" + (i + 1) + "次运行");
            Thread.yield();//暂停线程
        }
    }

   public static class SecThread extends Thread {
       @Override
       public void run() {
           for (int i = 0; i < 5; i++) {
               System.out.println("第二个线程的第" + (i + 1) + "次运行");
               Thread.yield();
           }
       }
   }

    public static void main(String[] args) {
        FirstThread mt = new FirstThread();
        SecThread mntt = new SecThread();
        mt.start();
        mntt.start();
    }
}

输出结果:
在实例五中,调用了yield()方法之后,当线程并不是转入被阻塞状态,它可以与其他等待执行的线程竞争CPU资源,如果此时它又抢占到CPU资源,就会出现连续运行几次的情况。
sleep()方法与yield()方法在使用时容易混淆,这两个方法之间的区别如下所示:

sleep()方法 yield()方法
使当前线程进入被阻塞状态 将当前线程转入暂停执行的状态
即使没有其他等待运行的线程,当前线程也会等待指定的时间 如果没有其他等待的线程,当前线程会马上恢复执行
其他等待执行的线程的机会是均等的 会运行优先级相同或更高的线程

示例七:模拟多人爬山。每个线程代表一个人,可设置每人爬山速度,每爬完100米显示信息,爬到终点时给出相应提示。
在这里插入图片描述
代码展示:

public class test3 implements Runnable {
    @Override
    public void run() {

        for (int i = 1; i <= 10; i++) {
            System.out.println(Thread.currentThread().getName()+"爬完"+(i*100)+"米!");
        }
        System.out.println(Thread.currentThread().getName()+"到达终点!");
    }
    public static void main(String[] args) throws InterruptedException {
        System.out.println("***开始爬山***");
        test3 t = new test3();
        Thread t1 = new Thread(t, "年轻人");
        Thread t2 = new Thread(t, "老年人");
        t1.start();
        t2.start();
        t2.sleep(100);
    }
}

输出结果:
在这里插入图片描述
示例八:模拟叫号看病。某科室一天需看普通号50个,特需号10个。特需号看病时间是普通号的2倍,开始时普通号和特需号并行叫号,叫到特需号的概率比普通号高,当普通号叫完第10号时,要求先看完全部特需号,再看普通号
使用多线程模拟这一过程。
在这里插入图片描述
代码展示:

public class test5 implements Runnable {
    @Override
    public void run() {
        for (int i = 1; i <= 10; i++) {
            System.out.println(Thread.currentThread().getName()+":"+i+"号病人在看病!");
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    public static void main(String[] args) {
        test5 t = new test5();
        Thread t1 = new Thread(t, "特需号");
        t1.setPriority(10);
        t1.start();

        for (int i = 1; i <= 50; i++) {
            Thread.currentThread().setName("普通号");
            System.out.println(Thread.currentThread().getName() + ":" + i + "号病人在看病!");
            try {
                Thread.sleep(50);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            if (i == 10) {
                try {
                    t1.join();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

输出结果:在这里插入图片描述

实现线程同步

当两个或多个线程需要访问同一资源时,需要以某种顺序来确保该资源在某一时刻只能被一个线程使用的方式称为线程同步。
采用同步线程来控制线程的执行就是同步方法和同步代码块两种方法。

同步方法

通过在方法声明中加入synchronize关键字来声明同步方法。
使用synchronize修饰的方法控制对类成员变量的访问。每个类实例对应一把锁,方法一旦执行,就独占该锁,知道该方法返回时才能将锁释放,此后被阻塞的线程方能获得该锁,重新进入可执行状态。这种机制确保了同一时刻对应每一个实例,其所声明为synchronize的方法只能有一个处于可执行状态,从而有效地避免了类成员变量的访问冲突。
同步方法的语法格式如下:
访问修饰符 synchronize 返回类型 方法名 {}
或者
synchronize 访问修饰符 返回类型 方法名{}
注意:
synchronize是关键字。
访问修饰符是指public、private等。

同步代码块

同一时刻只能有一个线程进入synchronized(this)同步代码块。
当一个线程访问一个synchronized(this)同步代码块时,其他synchronized(this)同步代码块同样被锁定。
当一个线程访问一个synchronized(this)同步代码块时,其他线程可以访问该资源的非synchronized(this)同步代码。
示例九:使用同步方法解决抢票问题。
代码展示:

public class TestTicket implements Runnable {
    int ticket = 10;
    int sold = 0;

    @Override
    public void run() {

        while (ticket > 0) {
            synchronized (this) {
                ticket--;
                sold++;

                if (ticket < 0) return;
                System.out.println(Thread.currentThread().getName() +
                        "买到了第" + sold + "张票,还剩余" + ticket);
                try {
                    Thread.sleep(30);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    public static void main(String[] args) {
        TestTicket t = new TestTicket();
        Thread t1 = new Thread(t, "12306");
        Thread t2 = new Thread(t, "携程");
        t1.start();
        t2.start();
    }
}

输出结果:在这里插入图片描述
同步方法的缺陷:如果将一个运行时间比较长的方法声明成synchronize将会影响效率。例如,将线程中的run()方法声明成synchronize,由于在线程的整个生命周期内它一直在运行,这样有可能导致run()方法会执行很长时间,那么其他的线程及得一直等到run()方法结束了才能执行。
示例十:模拟接力赛跑。多人参加1000米接力跑,每人跑100米,换下个选手,每跑10米显示信息。在这里插入图片描述
代码展示:

public class test6 implements Runnable {
    int chang=1000;
    @Override
    public void run() {
        while (chang > 0) {
            chang-=100;
            synchronized (this) {
                System.out.println(Thread.currentThread().getName() + "号选手拿到了接力棒!");
                for (int i = 10; i <= 100; i = i + 10) {
                    System.out.println(Thread.currentThread().getName()+"跑了"+i+"米!");
                }
            }
        }
    }

    public static void main(String[] args) {
        test6 t = new test6();
        for (int i = 1; i <=10 ; i++) {
            Thread t1 = new Thread(t,i+"");
            t1.start();
        }

    }
}

输出结果:
在这里插入图片描述

线程安全类型

在这里插入图片描述
常见类型比较:
StringBuffer && StringBuilder
前者线程安全,后者非线程安全
线程安全:synchronized 保证线程间隔离
String:不可被改变,真正意义上的安全
在频繁字符串拼接的情况下,速度非常慢
StringBuffer:线程安全,速度慢StringBuilder:线程不安全,速度快

总结

线程的创建方式:
继承Thread类
实现Runnble接口
实现Callable接口
线程的五个状态:
创建、就绪、阻塞、运行、死亡

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

大数据——Java多线程 的相关文章

  • Java中的整数除法[重复]

    这个问题在这里已经有答案了 这感觉像是一个愚蠢的问题 但我在 Java 文档中找不到答案 如果我声明两个 int 然后将它们相除 到底发生了什么 他们是否转换为floats doubles首先 划分 然后投射回integer 或者除法是作为
  • 这两个绑定声明与 Google Guice 有什么区别?

    有什么区别 bind FooImpl class in Scopes SINGLETON bind Foo class to FooImpl class and bind Foo class to FooImpl class in Scop
  • 生成固定长度的随机数组[重复]

    这个问题在这里已经有答案了 我只是想更改我的代码 以便每次运行代码时都会生成固定长度 100 个整数的随机数组 而不仅仅是在代码中包含一个预先设置的数组 我对此很陌生 所以只需要正确方向的指导 谢谢 public class Selecti
  • 通过 ant 构建脚本将命令行参数传递给 Java

    运行以下命令时 ant targetname Dk1 v1 Dk2 v2 我想要将命令行参数传递给java like java whatever Dk1 v1 Dk2 v2 我需要从 Java 代码访问这些参数System getPrope
  • 添加样式后如何重置回默认CSS?

    基本上 我通过添加如下样式类来更改 javafx 中文本字段的 css textfield getStyleClass add textfieldstyle 但后来我希望能够将其恢复到原来的样子 但由于本例中的原始外观是 JavaFX 的默
  • 创建 CXF Web 服务客户端时出现 ServiceConstructionException (scala+java+wsdl2java)

    这些其他问题暗示了解决方案 但我无法让它发挥作用 无法解析 http schemas xmlsoap org wsdl soap 的绑定 https stackoverflow com questions 26159206 could no
  • Spring Security“拒绝执行来自...的脚本”

    我正在 HTML 文件 thymeleaf 模板 中使用 Spring Security 和 Bootstrap 构建 Spring MVC 应用程序 Spring Security部分基于Spring Guide对于春季安全 http s
  • 当服务器仅从请求中读取标头时,Http 客户端未收到响应

    我在 Java 中搞乱了 HTTP 和套接字 希望你能对此有所了解 当我用 Java SE 11 编写的 HTTP 服务器没有读取整个请求然后响应时 客户端不会收到它或收到错误 这是为什么 在服务器读取整个请求之前 客户端是否无法读取响应
  • 为什么 JPA/hibernate 不能映射到 MySQL blob 类型?

    我收到以下错误 Caused by org hibernate HibernateException Wrong column type in TestTable for column PAYLOAD Found blob expected
  • 什么时候使用弱引用? [复制]

    这个问题在这里已经有答案了 我了解什么是 Java WeakReference 我想知道的是它通常用于解决哪种具体问题 有没有包含它们的模式 WeakReference and SoftReference当您想保留某些东西以备再次需要时使用
  • 从 MySql 迁移:MariaDB 服务器意外关闭客户端连接

    由于许可 商业使用原因 我们正在从 MySql 迁移到 MariaDB 我们已经成功用 MariaDB 客户端 jar 替换了 MySql 连接器 jar 第一次更改 现在正在尝试用 MariaDB 服务器替换 MySql 服务器而不更改数
  • 使用 JSeperator - Java 时出现异常间隙

    我一直在开发 Swing GUI 并在添加后出现一些不寻常和不需要的间隙JSeperator 知道如何删除它们吗 或者任何其他选择来很好地实现这一目标 视觉描述 之前差距就很明显了JLabel 速度 及之后JSlider 相关代码 cont
  • 如何反序列化数组 google-gson 内的数组

    我有这样的 JSON Answers Locale Ru Name Name1 Locale En Name Name2 Locale Ru Name Name3 Locale En Name Name4 正如你所看到的 我的数组里面有数组
  • 如何在 Java 中以编程方式获取接口的所有实现的列表?

    我可以通过反思或类似的方式来做到这一点吗 我已经搜索了一段时间 似乎有不同的方法 这里总结一下 反思 https github com ronmamo reflections如果您不介意添加依赖项 该库非常受欢迎 它看起来像这样 Refle
  • 三角形未在 OSX 上的 OpenGL 2.1 中绘制

    我正在学习有关使用 OpenGL 在 Java 中创建游戏引擎的教程 我正在尝试在屏幕上渲染一个三角形 一切运行良好 我可以更改背景颜色 但三角形不会显示 我还尝试运行作为教程系列的一部分提供的代码 但它仍然不起作用 教程链接 http b
  • 返回数据集的 kSoap 和 .Net Web 服务

    我知道使用数据集是一个很大的罪恶 但由于该服务不在我的控制之下 并且创建代理服务的前景是不可能的 我想看看是否有人创建了可以使用 kSoap 序列化器反序列化的类结构 或者我是否吸错了东西 同时要启动它 看看是否可行 以下是预期的结果数据
  • 缓冲区溢出(与)缓冲区溢出(与)堆栈溢出[重复]

    这个问题在这里已经有答案了 可能的重复 堆栈溢出和缓冲区溢出有什么区别 https stackoverflow com questions 1120575 what is the difference between a stack ove
  • 优化Gson反序列化

    优化反序列化的最佳方法是什么 我目前正在使用标准 Gson toJson 和 Gson fromJson 方法来序列化和反序列化一些复杂对象 我希望尽可能减少反序列化时间 如果重要的话 我的最复杂的对象包含 43 个变量 如果你想使用 Gs
  • 在 WildFly 10 中添加 jar 作为部署

    有没有办法 我们可以将 jar 部署为库 部署WildFly 10就像我们可以做到的那样weblogic服务器 或者我们可以将 jar 放在服务器的任何文件夹中并将这些依赖项定义为provided 我得到了什么部署方式jars on Wil
  • 像 Java 一样覆盖 Objective-C 类中的方法

    我经常使用此语句来扩展类 而不需要编写整个单独的文件 假设 ClassFromFramework 是库中包含的框架的一部分的类 public ClassFromFramework public String myMethod operati

随机推荐

  • mysql 建表语句 stored as_Druid 解析Hive建表语句解析报错

    Druid 版本 com alibaba druid spring boot starter 1 2 3 Hive 建表SQL create table ads data sale detail one23 like ads data sa
  • HashMap的底层实现原理

    HashMap的底层实现原理 一 HashMap的底层实现原理 HashMap 在 JDK1 8 之前的实现方式 数组 链表 JDK1 8之后的实现方式 数组 链表 红黑树 原理 当你 new 一个 HashMap 的时候 它底层并没有创建
  • 有哪些副业适合教师?有哪些是教师禁止的副业?

    有哪些副业适合教师 有哪些是教师禁止的副业 老师做副业选择挺多的 但是很多人一上来就说什么辅导班 做点小生意之类的 大家怕是还不知道对于在编教师有些兼职副业是做不了的 有些事没有禁止可以做的 还有一些是鼓励做的 那些副业是老师坚决不能碰的
  • Java初学之标识符

    目录 一 什么是标识符 二 标识符的命名规则 三 标识符的命名规范 一 什么是标识符 标识符 identifier 是指用来标识某个实体的一个符号 在不同的应用环境下有不同的含义 在java源程序中 凡是程序员有权利自己命名的单词都是标识符
  • 关于数据导入,教你几招

    前言 我们知道 数据库是存放数据的仓库 日常我们使用数据库也是为了存储数据 和数据库打交道总免不了要进行数据导入工作 工作中也可能遇到各种不同的数据导入需求 本篇文章主要分享下数据导入相关的小技巧 希望你能学到几招 1 弄清需求是关键 在进
  • AIX 常用命令

    查看所有vg对应的lv lsvg o lsvg i l 查看一个lv的详细细心 lv对应的日志文件 getlvcb AT fslv01 VGDA与ODM的同步 synclvodm v vght vg 名字 umount被占用删除 fuser
  • TortoiseGit 入门指南05:推送和拉取

    本节所讲内容均涉及到 远端版本库 版本库 的概念在 TortoiseGit 入门指南02 创建和克隆仓库 中提到过 它是工作目录下面的一个名为 git 的隐藏目录 我们每一次提交 每一个分支都会保存在版本库中 这个版本库就在我们电脑上的某个
  • C算法:冒泡排序算法(超级详细)!!!

    冒泡排序算法 冒泡排序是一种简单的排序算法 它也是一种稳定排序算法 其实现原理是重复扫描待排序序列 并比较每一对相邻的元素 当该对元素顺序不正确时进行交换 一直重复这个过程 直到没有任何两个相邻元素可以交换 就表明完成了排序 一般情况下 称
  • 常用的三种代码宏定义

    常用的三种代码宏定义 方式一 if endif 方式二 ifdef endif 方式一 if和方式二 ifdef别混搅 方式三 ifndef define else endif 方式一 if endif define LEDTEST 1 1
  • 文件解压缩操作

    文件解压缩操作 package com general system import java io File import java io FileOutputStream import java io IOException import
  • 无监督学习(含自编码器在MNIST上的图片重建实战)

    目录 1 无监督特征学习 1 1 PCA 主成分分析 1 2 稀疏编码 1 3 自编码器 2 自编码器在MNIST上的图片重建实战 3 自编码器变种 3 1 稀疏自编码器 3 2 堆叠自编码器 3 3 降噪自编码器 3 4 对抗自编码器 3
  • 【Qt5】频繁调用update()若干时间后无法自动重绘界面的问题

    最近在项目中遇到了这样的问题 程序的结构 主线程用于界面控制 线程1用于生成显示内容 线程2用于精确控制在正确的时刻控制界面显示生成的内容 实现方式 在线程2中直接调用显示控件的update 方法 让主线程重绘 运行效果 运行开始后的一段时
  • git创建本地仓库的三种方法

    首先新建文件夹E git repository repo1 然后打开该目录 接下来 有三种方式创建本地仓库 第一种方法 右键 单击git GUI here 点击创建仓库 然后关闭即可 此时可以看到新生成的文件夹 git 注意 git是隐藏文
  • Hive 分组取Top N

    成绩表S 字段sid cid score 求每门课程的前2名与后2名sid with a as select sid rank over distribute by cid sort by score rn rank over distri
  • 入门电机系列之3舵机

    入门电机系列 基于STM32硬件 本文章学习借鉴于野火团队资料 以表感谢 官网http products embedfire com 舵机的原理与应用 文章目录 入门电机系列 基于STM32硬件 前言 一 舵机的分类 舵机结构 舵机工作原理
  • 安装Java后端钉钉新的jar包指令

    install install file Dfile lib dingtalk sdk java taobao sdk java auto 1479188381469 20200403 jar DgroupId com taobao Dar
  • linux命令高亮显示,linux命令行高亮显示

    Loading gt 我们常用命令的朋友知道 纯黑白的看命令 时间长了很是不舒服 那么接下来就进行下命令行高亮的个性化的配置吧 想永久性的设置命令行高亮的效果 就需要修改 bashrc配置文件 一 进入 bashrc文件目录 bashrc这
  • 了解基础的docker容器化

    一 什么是docker容器 docker容器简单说来就是码头工具 docker是一个开源的的应用容器引擎 docker的图标是一个鲸鱼上有很多集装箱 docker就是鲸鱼 他上面的集装箱就代表各个容器 docker容器在目前的环境中大部分公
  • Freemarker常用语法简例(二)

    为使用Freemarker模板时的关键性语法编写代码示例或说明 主要用于回忆性检索或速查 阅读需要一定代码基础或对Freemarker有了解 常用Freemarker语法简例 常用Freemarker语法简例 二 bool值 lt 输出 t
  • 大数据——Java多线程

    多线程 认识线程 进程 线程 多线程的优势 编写线程类 使用Thread类创建线程 使用Runnable接口创建线程 使用Callable接口创建线程 线程的状态 新生状态 New Thread 可运行状态 Runnable 阻塞状态 Bl