java基础语法(19)| 线程

前言

Hello,大家好!很开心与你们在这里相遇,我是一个喜欢文字、喜欢有趣的灵魂、喜欢探索一切有趣事物的女孩,想与你们共同学习、探索关于IT的相关知识,希望我们可以一路陪伴~

1. 多线程概述

并发与并行

  • 什么是并发

指两个或多个事件在同一个时间段内发生

  • 什么是并行

指两个或多个事件在同一时刻发生(同时发生)

 进程

是指一个内存中运行的应用程序,每个进程都有一个独立的内存空间,一个应用程序可以同时运行多个进程;进程也是程序的一次执行过程,是系统运行程序的基本单位;系统运行一个程序即是一个进程从创建、运行到消亡的过程。

线程

线程是进程中的一个执行单元,负责当前进程中程序的执行,一个进程中至少有一个线程。一个进程中是可以有多个线程的,这个应用程序也可以称之为多线程程序。

线程调度

  • 分时调度

所有线程轮流使用 CPU 的使用权,平均分配每个线程占用 CPU 的时间

  • 抢占式调度  

 优先让优先级高的线程使用 CPU,如果线程的优先级相同,那么会随机选择一个(线程随机性),Java使用的为抢占式调度。

 2. 多线程创建

 Java使用java.lang.Thread类代表线程,所有的线程对象都必须是Thread类或其子类的实例。每个线程的作用是完成一定的任务,实际上就是执行一段程序流即一段顺序执行的代码。Java使用线程执行体来代表这段程序流。

 继承Thread类

继承Thread类创建并启动多线程的步骤如下:

  1. 定义Thread类的子类,并重写该类的run()方法,该run()方法的方法体就代表了线程需要完成的任务,因此把run()方法称为线程执行体。

  2. 创建Thread子类的实例,即创建了线程对象

  3. 调用线程对象的start()方法来启动该线程

 定义线程类

public class MyThread extends Thread {
	/**
	 * 重写run方法,完成该线程执行的逻辑
	 */
	@Override
	public void run() {
		for (int i = 0; i < 10; i++) {
			System.out.println("HelloWolrd!"+i);
		}
	}
}

测试类

public class Demo01 {
    public static void main(String[] args) {
        // MyThread my = new MyThread();
        //这不是启动线程,相当于调了run()方法,只是普通调用
        // my.run();
        // my.run();

        //IllegalThreadStateException 非法的线程态态异常
        //为什么呢? 因为你启动两次,并不是两个线程
        // my.start();
        // my.start();

        MyThread my = new MyThread();
        MyThread my2 = new MyThread();
        my.start();
        my2.start();
    }
}

获取名字和设置名字

public class MyThread extends Thread{
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            System.out.println(getName()+" : "+i);
        }
    }
}
    public static void main(String[] args) {
        MyThread my = new MyThread();
        MyThread my2 = new MyThread();

        my.setName("jack");
        my2.setName("rose");

        my.start();
        my2.start();

    }

实现Runnable接口

实现Runnable接口创建并启动多线程的步骤如下:

1.定义Runnable接口的实现类,并重写该接口的run()方法,该run()方法的方法体同样是该线程的线程执行体。

2.创建Runnable实现类的实例,并以此实例作为Thread的target来创建Thread对象,该Thread对象才是真正的线程对象。

3.调用线程对象的start()方法来启动线程。

 Runnable接口

public class MyRunnable implements Runnable {
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            System.out.println(Thread.currentThread().getName()+" : "+i);
        }
    }
}

 测试类

    public static void main(String[] args) {
        MyRunnable my = new MyRunnable();
        //起名字方式1
        // Thread t1 = new Thread(my,"jack");
        // Thread t2 = new Thread(my,"rose");

        Thread t1 = new Thread(my);
        Thread t2 = new Thread(my);

        //起名字方式2
        t1.setName("jack");
        t2.setName("rose");

        //启动线程
        t1.start();
        t2.start();
    }

Thread和Runnable的区别

public class ThreadTest1 implements Runnable {
    private int num = 10;

    @Override
    public void run() {
        for (int i = 0; i <= 100; i++) {
            if (num > 0) {
                System.out.println(Thread.currentThread().getName()+"执行结果:" + (num--));
            }
        }
    }

    public static void main(String[] args) {
        ThreadTest1 t1 = new ThreadTest1();

        Thread t01 = new Thread(t1, "线程1");
        Thread t02 = new Thread(t1, "线程2");
        Thread t03 = new Thread(t1, "线程3");

        t01.start();
        t02.start();
        t03.start();
    }
}
public class ThreadTest2 extends Thread {
    private int num = 10;

    @Override
    public void run() {

        for(int i =0; i <=100; i++) {
            if(num >0) {
                System.out.println(Thread.currentThread().getName()+"执行结果:"+(num--));
            }
        }
    }

    public static void main(String[] args) {

        ThreadTest2 t01 = new ThreadTest2();
        ThreadTest2 t02 = new ThreadTest2();
        ThreadTest2 t03 = new ThreadTest2();

        t01.start();
        t02.start();
        t03.start();
    }
}

如果一个类继承Thread,则不适合资源共享。但是如果实现了Runable接口的话,则很容易的实现资源共享。

实现Runnable接口比继承Thread类所具有的优势  

 从上面的运行结果可以看出,两者的区别。
实现Runnable接口的,对于三个线程来说共享的是ThreadTest1对象的资源。
继承Thread类,三个线程都是独立的运行,线程间不共享资源。

所以可以总结出以下区别:

1.Runnable接口的话,可以避免单继承的局限性,具有较强的健壮性。

2.Runnable可以实现资源的共享,同时处理同一资源。

3.Thread类的线程间都是独立运行的,资源不共享。

4.继承Thread类不再被其他类继承(java不存在多继承) 

3. 线程调度

方法名说明
public static void sleep(long millis)在指定的毫秒数内让当前正在执行的线程休眠(暂停执行)
public final void join()等待该线程终止
public final void setDaemon(boolean on)将该线程标记为守护线程或用户线程
public final void setPriority(int newPriority)更改线程的优先级。默认为5, 最小级别:1 ,最大级别:10
public static void yield()暂停当前正在执行的线程对象,并执行其他线程。

设置线程优先级

public class ThreadPriority extends  Thread {
    @Override
    public void run() {
        for (int i = 0; i <20 ; i++) {
            System.out.println(getName()+":"+i);
        }
    }
}
public class Test {
    public static void main(String[] args) {

        ThreadPriority t1 = new ThreadPriority();
        ThreadPriority t2 = new ThreadPriority();
        ThreadPriority t3 = new ThreadPriority();

        t1.setName("jack");
        t2.setName("rose");
        t3.setName("yiyan");

        // System.out.println(t1.getPriority());//5
        // System.out.println(t2.getPriority());//5
        // System.out.println(t3.getPriority());//5

        //参数(1-10)
        // t1.setPriority(0);//IllegalArgumentException 非法参数异常
        t1.setPriority(1);
        t2.setPriority(10);
        t3.setPriority(5);
        //设置优先级只是尽可以保证线程的优先级并不能完全保证,线程本身就是随机

        t1.start();
        t2.start();
        t3.start();
    }
}

线程休眠

public static void sleep(long millis) 停顿一会再走

public class Threadsleep  extends  Thread{

    @Override
    public void run() {
        for (int i = 0; i <100 ; i++) {
            System.out.println(getName()+": "+i+", 日期:"+ new Date());

            //困了,我睡一会
            try {
                Thread.sleep(10000000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
    public static void main(String[] args) {

        Threadsleep t1 = new Threadsleep();
        Threadsleep t2 = new Threadsleep();
        Threadsleep t3 = new Threadsleep();

        t1.setName("jack");
        t2.setName("rose");
        t3.setName("yanqi");

        t1.start();
        t2.start();
        t3.start();
    }

线程的加入

public final void join():等待该线程终止。

先把加入的这个线程走完(终止)然后其他的线程自已去抢

public class ThreadJoin extends  Thread{
    @Override
    public void run() {
        for (int i = 0; i < 100 ; i++) {
            System.out.println(getName()+": "+i);
        }
    }
}
public class Test {
    public static void main(String[] args) {

        ThreadJoin tj1 = new ThreadJoin();
        ThreadJoin tj2 = new ThreadJoin();
        ThreadJoin tj3 = new ThreadJoin();

        tj1.setName("jack");
        tj2.setName("rose");
        tj3.setName("yiyan");

        tj1.start();
        try {
            tj1.join();//加入线程,tj1走完之后,tj2,tj3才可以去抢
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        tj2.start();
        tj2.join();	
        
        tj3.start();
    }
}

线程礼让

public static void yield():暂停当前正在执行的线程对象,并执行其他线程。

让多个线程的执行更和谐,但是不能靠它保证一人一次。

public class ThreadYield  extends  Thread{

    @Override
    public void run() {
        for (int i = 0; i <10 ; i++) {
            System.out.println(getName()+": "+ i );
			if(i%3==0)
            	//线程礼让
            	Thread.yield();
        }
    }
}
public class Test {
    public static void main(String[] args) {
        ThreadYield ty1 = new ThreadYield();
        ThreadYield ty2 = new ThreadYield();
        ThreadYield ty3 = new ThreadYield();

        ty1.setName("jack");
        ty2.setName("rose");

        ty1.start();
        ty2.start();
    }
}

线程守护

public final void setDaemon(boolean on):将该线程标记为守护线程、后台线程。

jvm的垃圾回收,就是一个后台线程。 该方法必须在启动线程前调用。

public class ThreadDaemon extends  Thread {d
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            System.out.println(getName()+": "+i);
        }
    }
}
public class Test {
    public static void main(String[] args) {
        ThreadDaemon t1 = new ThreadDaemon();
        ThreadDaemon t2 = new ThreadDaemon();

        t1.setName("关习习");
        t2.setName("张飞");

        //设置守护线程,一定在启动之前调用
        t1.setDaemon(true);
        t2.setDaemon(true);

        t1.start();
        t2.start();

        Thread.currentThread().setName("刘备");
        for (int i = 1; i <=5 ; i++) { //主线程,main方法,当前线程走到5的时候,t1,t2都会挂掉
            System.out.println(Thread.currentThread().getName()+": "+i);
        }

    }
}

线程停止

public final void stop():让线程停止,过时了,但是还可以使用。

public void interrupt():中断线程。 把线程的状态终止,并抛出一个InterruptedException。

public class ThreadStop  extends  Thread{
    @Override
    public void run() {
        System.out.println("开始执行:"+new Date());

        try {
            Thread.sleep(10000);     //睡了10秒
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("结果执行:"+new Date());
    }
}
public class Test {
    public static void main(String[] args) {
        ThreadStop t1 = new ThreadStop();
        t1.start();

        try {
            //如果你睡3秒还不睡醒,就干掉你
            Thread.sleep(3000);
            // t1.stop();//已过时,但可以用。如果后面还有代码就不没去运行
            t1.interrupt();//判断当前线程中断,不影响后面的执行
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }
}

4. 线程安全

多线程执行的结果和单线程运行的结果是一样的,就是线程安全的。

为了保证每个线程都能正常执行原子操作,Java引入了线程同步机制。

  • ==同步代码块==

  • ==同步方法==

  • ==Lock锁==

同步代码块

synchronized 关键字可以用于方法中的某个区块中,表示只对这个区块的资源实行互斥访问。

 格式:

synchronized(同步锁的对象){ 
	需要同步操作的代码 
}

同步锁

对象的同步锁只是一个概念,可以想象为在对象上标记了一个锁

在任何时候,最多允许一个线程拥有同步锁,谁拿到锁就进入代码块,其他的线程只能在外等着 (BLOCKED)。

  • 锁对象 可以是任意类型。

  • 多个线程对象 要使用同一把锁。

 线程类

public class RunnableImpl implements Runnable{
    //定义一个多个线程共享的票源
    private  int ticket = 100;

    //创建一个锁对象
    Object obj = new Object();

    //设置线程任务:卖票
    @Override
    public void run() {
        //使用死循环,让卖票操作重复执行
        while(true){
           //同步代码块
            synchronized (obj){
                //先判断票是否存在
                if(ticket>0){
                    //提高安全问题出现的概率,让程序睡眠
                    try {
                        Thread.sleep(10);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                    //票存在,卖票 ticket--
                    System.out.println(Thread.currentThread().getName()+"-->正在卖第"+ticket+"张票");
                    ticket--;
                }
            }
        }
    }
}

测试类

public class Demo01Ticket {
    public static void main(String[] args) {
        //创建Runnable接口的实现类对象
        RunnableImpl run = new RunnableImpl();
        //创建Thread类对象,构造方法中传递Runnable接口的实现类对象
        Thread t0 = new Thread(run,"窗口1");
        Thread t1 = new Thread(run,"窗口2");
        Thread t2 = new Thread(run,"窗口3");
        //调用start方法开启多线程
        t0.start();
        t1.start();
        t2.start();
    }
}

同步的好处和弊端

同步的好处:
   同步的出现解决了多线程的安全问题
   
同步的弊端:
     当线程相当多时,因为每个线程都会去判断同步上的锁,这是很耗费资源的,无形中会降低程序的运行效率。

回顾: 线程安全,效率低

 同步方法

使用synchronized修饰的方法,就叫做同步方法,保证A线程执行该方法的时候,其他线程只能在方法外 等着。

 格式

public synchronized void method(){
    可能会产生线程安全问题的代码 
}

同步方法中的锁是谁?

  • 对于非static方法,同步锁就是this。

  • 对于static方法,我们使用当前方法所在类的字节码对象(类名.class)。

  • synchronized关键字加到static静态方法上是给Class类上锁,而synchronized关键字加到非static静态方法上是给对象上锁(一个是对象锁,另外一个是Class锁)

public class RunnableImpl implements Runnable{
    //定义一个多个线程共享的票源
    private static int ticket = 100;


    //设置线程任务:卖票
    @Override
    public void run() {
        System.out.println("this:"+this);
        
        //使用死循环,让卖票操作重复执行
        while(true){
            payTicketStatic();
        }
    }

    /*
        【静态】的同步方法
        锁对象是谁?
        不能是this
        this是创建对象之后产生的,静态方法优先于对象
        静态方法的锁对象是本类的class属性-->class文件对象(反射)
     */
    public static /*synchronized*/ void payTicketStatic(){
        synchronized (RunnableImpl.class){
            //先判断票是否存在
            if(ticket>0){
                //提高安全问题出现的概率,让程序睡眠
                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                //票存在,卖票 ticket--
                System.out.println(Thread.currentThread().getName()+"-->正在卖第"+ticket+"张票");
                ticket--;
            }
        }
    }

    /*
        定义一个【非静态】同步方法
        同步方法也会把方法内部的代码锁住
        只让一个线程执行
        同步方法的锁对象是谁?
        就是实现类对象 new RunnableImpl()
        也是就是this
     */
    public /*synchronized*/ void payTicket(){
        synchronized (this){
            //先判断票是否存在
            if(ticket>0){
                //提高安全问题出现的概率,让程序睡眠
                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                //票存在,卖票 ticket--
                System.out.println(Thread.currentThread().getName()+"-->正在卖第"+ticket+"张票");
                ticket--;
            }
        }

    }
}

Lock锁

java.util.concurrent.locks.Lock机制提供了比synchronized代码块synchronized方法更广泛的锁定操作, 同步代码块/同步方法具有的功能Lock都有,除此之外更强大,更体现面向对象。

 Lock接口提供的方法

方法名说明
public void lock()加同步锁。
public void unlock()释放同步锁。
/*
    卖票案例出现了线程安全问题
    卖出了不存在的票和重复的票

    解决线程安全问题的三种方案:使用Lock锁
    java.util.concurrent.locks.Lock接口
    Lock 实现提供了比使用 synchronized 方法和语句可获得的更广泛的锁定操作。
    Lock接口中的方法:
        void lock()  获取锁。
        void unlock()  释放锁。
    java.util.concurrent.locks.ReentrantLock implements Lock接口


    使用步骤:
        1.在成员位置创建一个ReentrantLock对象
        2.在可能会出现安全问题的代码前调用Lock接口中的方法lock获取锁
        3.在可能会出现安全问题的代码后调用Lock接口中的方法unlock释放锁
        
    注:如果不解锁,那么就会出现只执行一个线程的情况,体现不出多线程    
 */
public class RunnableImpl implements Runnable{
    //定义一个多个线程共享的票源
    private  int ticket = 100;

    //1.在成员位置创建一个ReentrantLock对象
    Lock l = new ReentrantLock();

    //设置线程任务:卖票
    @Override
    public void run() {
        //使用死循环,让卖票操作重复执行
        while(true){
            //2.在可能会出现安全问题的代码前调用Lock接口中的方法lock获取锁
            l.lock();

            //先判断票是否存在
            if(ticket>0){
                //提高安全问题出现的概率,让程序睡眠
                try {
                    Thread.sleep(10);
                    //票存在,卖票 ticket--
                    System.out.println(Thread.currentThread().getName()+"-->正在卖第"+ticket+"张票");
                    ticket--;
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }finally {
                    //3.在可能会出现安全问题的代码后调用Lock接口中的方法unlock释放锁
                    l.unlock();//无论程序是否异常,都会把锁释放
                }
            }
        }
    }
}

继承Thread类-实现卖票

继承自Thread类的线程类,要实现资源共享,在成员变量前加static,成类级别的资源了。

 同步代码块

public class MyThread extends Thread {
    //把当前的票源修改为static
    private static int ticket = 100;

    @Override
    public void run() {

        //为了卖票一直操作
        while (true) {

            //同步代码块的锁对象是其本身.class
            synchronized (MyThread.class) {
                //判断票是否存在
                if (ticket > 0) {
                    //模拟出票真实情况
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                    //卖票
                    System.out.println(getName() + "-->正在卖第 " + ticket + " 张票");
                    ticket--;
                }
            }
        }
    }
}
public static void main(String[] args) {
        MyThread my1 = new MyThread();
        MyThread my2 = new MyThread();
        MyThread my3 = new MyThread();

        my1.setName("窗口1");
        my2.setName("窗口2");
        my3.setName("窗口3");

        my1.start();
        my2.start();
        my3.start();
    }

同步方法

public class MyThread extends Thread {
    //把当前的票源修改为static
    private static int ticket = 100;

    @Override
    public void run() {

        //为了卖票一直操作
        while (true) {
          payTic();
        }
    }

    //继承thread类的同步方法,只能是静态
    private static synchronized void payTic() {
        //判断票是否存在
        if (ticket > 0) {

            //模拟出票真实情况
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            //卖票
            System.out.println(Thread.currentThread().getName() + "-->正在卖第 " + ticket + " 张票");
            ticket--;
        }
    }
}
public static void main(String[] args) {
        MyThread my1 = new MyThread();
        MyThread my2 = new MyThread();
        MyThread my3 = new MyThread();

        my1.setName("窗口1");
        my2.setName("窗口2");
        my3.setName("窗口3");

        my1.start();
        my2.start();
        my3.start();
    }

Lock方法

package cn.yanqi_06;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class MyThread extends Thread {
    //把当前的票源修改为static
    private static int ticket = 100;

    //继承Trhead类的lock锁一定是静态的
    private static Lock l = new ReentrantLock();

    @Override
    public void run() {

        //为了卖票一直操作
        while (true) {

            l.lock();
            //判断票是否存在
            if (ticket > 0) {

                //模拟出票真实情况
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                //卖票
                System.out.println(Thread.currentThread().getName() + "-->正在卖第 " + ticket + " 张票");
                ticket--;
            }
            l.unlock();
        }
    }
}
public static void main(String[] args) {
        MyThread my1 = new MyThread();
        MyThread my2 = new MyThread();
        MyThread my3 = new MyThread();

        my1.setName("窗口1");
        my2.setName("窗口2");
        my3.setName("窗口3");

        my1.start();
        my2.start();
        my3.start();
    }

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Midjourney指南 - 生成高分辨率图片(内容已更新至V5)

Midjourney 首先为每个作业生成一个低分辨率图片网格(2x2)。你可以在选择其中任一图片&#xff0c;使用 Midjourney upscaler 来增加尺寸并添加更多细节。有多种可用于放大图像的放大模型。 每个图像网格下方的按钮用于放大所选图像。U1 U2 U3 U4 注&#xff1a;upscaler 以下…

震惊金融界!巴克莱银行报告称去年投资诈骗激增29%

巴克莱银行 (Barclays) 发布的令人担忧的数据显示&#xff0c;在过去一年里&#xff0c;投资诈骗数量激增了 29%&#xff0c;震惊了金融界。这些诈骗给该银行的活期账户客户造成了巨大损失&#xff0c;占欺诈者损失资金的最高比例&#xff0c;平均索赔超过14,000英镑。 投资骗…

如何合理利用多个中国大陆小带宽服务器?

我们知道在中国大陆带宽单价非常昂贵&#xff0c;一个1Mbps 带宽的机子一年就得卖好几百人民币&#xff0c;这是不值当的&#xff0c;当然我们可以去低价漂阿里云、腾讯云的轻量服务器&#xff0c;99包年&#xff0c;但是带宽太小很难崩。 所以&#xff0c;我们必须构建一个能够…

怎么购买GPT api

怎么购买GPT api GPT API是由OpenAI提供的一种应用程序编程接口&#xff08;API&#xff09;&#xff0c;允许开发者通过编程方式访问OpenAI开发的GPT&#xff08;Generative Pre-trained Transformer&#xff09;模型。GPT是一种基于深度学习的自然语言处理技术&#xff0c;主…

刷题之Leetcode19题(超级详细)

19.删除链表的倒数第N个节点 力扣题目链接(opens new window)https://leetcode.cn/problems/remove-nth-node-from-end-of-list/ 给你一个链表&#xff0c;删除链表的倒数第 n 个结点&#xff0c;并且返回链表的头结点。 进阶&#xff1a;你能尝试使用一趟扫描实现吗&#x…

爱普生计时设备AUTOMOTIVE RA8900CE DTCXO RTC

主要特点出场已校准带有DTCXO的RTC&#xff0c;并且内部集成晶体单元高精度: 3.4 ppm 40 to 85 C(9 s/月.)时钟输出:1 Hz.1024 Hz.32.768 kHzI 2 C Interface: Fast mode (400 kHz)The l2C-Bus is a trademark ofNXP Semiconductors供电电压: 2.5-5.5 V(main),1.6-5.5 V(备份电…

软考132-上午题-【软件工程】-沟通路径

一、定义 1-1、沟通路径1 沟通路径 1-2、沟通路径2 沟通路径 n-1 二、真题 真题1&#xff1a; 真题2&#xff1a; 真题3&#xff1a;

国外AI programmer 后来者SWE-agent,Devin不在孤寂

如果你正在寻找一种人工智能(AI)自主软件工程师Devin的替代品,它的强大程度足以与最近宣布的自主AI编码平台竞争。这位新手就是SWE-Agent!它是由普林斯顿大学NLP小组创造的开源人工智能程序员,旨在自主解决GitHub问题并实现最先进的性能,估值目标为20亿美元。SWE Agent在S…

jar包混淆

由于开发需要&#xff0c;不让甲方反编译出源代码。 命令如下&#xff1a; java -jar classfinal-fatjar-1.2.1.jar -file mis-admin.jar -libjars mis-ducg-3.5.0.jar -packages com.mis,cn.edu -pwd 123456 -Y 反编译软件编译的源码如下&#xff1a;直接null&#xff0c;成…

k8s使用harbor私有仓库镜像 —— 筑梦之路

官方文档: Secret | Kubernetes ImagePullSecrets的设置是kubernetes机制的另一亮点&#xff0c;习惯于直接使用Docker Pull来拉取公共镜像&#xff0c;但非所有容器镜像都是公开的。此外&#xff0c;并不是所有的镜像仓库都允许匿名拉取&#xff0c;也就是说需要身份认证&…

回归预测 | Matlab实现GWO-GPR灰狼算法优化高斯过程回归多变量回归预测

回归预测 | Matlab实现GWO-GPR灰狼算法优化高斯过程回归多变量回归预测 目录 回归预测 | Matlab实现GWO-GPR灰狼算法优化高斯过程回归多变量回归预测预测效果基本介绍程序设计参考资料 预测效果 基本介绍 Matlab实现GWO-GPR灰狼算法优化高斯过程回归多变量回归预测 1.Matlab实现…

Windows如何下载Bun并在前端Vue或React项目上替代Yarn或Npm

Bun Bun网站 Bun 在 Windows 上下载并安装 Bun 非常简单。你可以使用以下命令在 Windows 10 或更高版本上安装 Bun powershell -c "irm bun.sh/install.ps1 | iex"“powershell”不是内部或外部命令&#xff0c;也不是可运行的程序或批处理文件 PowerShell 命令解决…

JET毛选学习笔记:如何利用《实践论》学习实验

一、个人背景介绍 本人本科读的是预防医学专业&#xff08;因为没考上临床&#xff09;&#xff0c;硕博连读&#xff08;报名人少&#xff0c;我报了就得了&#xff09;的时候专业是流行病与卫生统计学&#xff0c;除了学习流行病学、统计学&#xff08;忘得差不多了&#xf…

Linux 操作系统指令和Vscdoe安装

1、Linux系统介绍 Linux系统的背景介绍我就不介绍了&#xff0c;有兴趣的可以去看看其发展史。 1.1 Linux操作系统的主要特点 Linux操作系统的重要思想&#xff1a;一切皆文件 Linux操作系统的特性&#xff1a; 完全免费 支持多平台 支持多用户、多任务 有良好的界面 完美兼容…

市场复盘总结 20240417

仅用于记录当天的市场情况&#xff0c;用于统计交易策略的适用情况&#xff0c;以便程序回测 短线核心&#xff1a;不参与任何级别的调整&#xff0c;采用龙空龙模式 一支股票 10%的时候可以操作&#xff0c; 90%的时间适合空仓等待 二进三&#xff1a; 进级率 100% 最常用的二…

phpMyadmin 设置显示完整内容

额外选项这里&#xff0c;默认部分内容改成完整内容 方案&#xff1a; 版本>4.5.4.1&#xff0c;修改文件&#xff1a;config.inc.php&#xff0c;添加一行代码&#xff1a; if ( !isset($_REQUEST[pftext])) $_REQUEST[pftext] F;

【算法刷题 | 回溯思想 07】4.18(全排列、全排列 ||)

文章目录 11.全排列11.1题目11.2解法&#xff1a;回溯11.2.1回溯思路&#xff08;1&#xff09;函数返回值以及参数&#xff08;2&#xff09;函数返回值&#xff08;3&#xff09;遍历过程 11.2.2代码实现 12.全排列 ||12.1题目12.2解法&#xff1a;回溯12.2.1回溯思路12.2.3代…

LeetCode 506.和为K的子数组

目录 题目描述 方法一 三重循环暴力 思路&#xff1a; 代码&#xff1a; 方法二 暴力一点点前缀和 思路&#xff1a; 代码&#xff1a; 方法三 前缀和哈希表 思路&#xff1a; 代码&#xff1a; 题目描述 给你一个整数数组 nums 和一个整数 k &#xff0c;请你统计并…

一拓门窗逆势而上,铸就品牌故事

随着恒大暴雷&#xff0c;陆陆续续许多房企也敲响警钟&#xff0c;作为房地产下游产业的门窗行业也感到了寒流来袭。各地楼盘交房量都在逐步减少&#xff0c;业主装修率与所投入的装修资金也在减少。在这样的大环境之下&#xff0c;行业内投资意愿减弱&#xff0c;许多门窗厂也…

OpenMesh 网格平均曲率计算

文章目录 一、简介二、实现代码三、实现效果参考资料一、简介 根据 Laplace-Beltrami 算子与平均曲率法向的关系: 又根据余切 Laplace-Beltrami 算子的定义: 其中 Ai 为该点邻域面积,取 Voronoi cell 面积如下: 得到
最新文章