黑马程序员并发编程笔记(二)--java线程基本操作和理解

2023-11-10

3.java进程的基本操作

3.1.创建进程

方法一,直接使用 Thread
// 构造方法的参数是给线程指定名字,,推荐给线程起个名字(用setName()也可以)
Thread t1 = new Thread("t1") {
 @Override
 // run 方法内实现了要执行的任务
 public void run() {
 log.debug("hello");
 }
};
t1.start();
方法二,使用 Runnable 配合 Thread

把【线程】和【任务】(要执行的代码)分开,Thread 代表线程,Runnable 可运行的任务(线程要执行的代码)Test2.java

// 创建任务对象
Runnable task2 = new Runnable() {
 @Override
 public void run() {
 log.debug("hello");
 }
};
// 参数1 是任务对象; 参数2 是线程名字,推荐给线程起个名字
Thread t2 = new Thread(task2, "t2");
t2.start();

1.8后用lambda表达式来简化写法

QQ截图20220121101957

// 创建任务对象
Runnable task2 = () -> log.debug("hello");
// 参数1 是任务对象; 参数2 是线程名字,推荐
Thread t2 = neaw Thread(task2, "t2");
t2.start();

也可以更简略一点

// 参数1 是任务对象; 参数2 是线程名字,推荐
Thread t2 = neaw Thread(() -> log.debug("hello"), "t2");
t2.start();

idea里 lamba表达式简化快捷键: alt +enter

小结

方法1 是把线程和任务合并在了一起,方法2 是把线程和任务分开了,用 Runnable 更容易与线程池等高级 API 配合,用 Runnable 让任务类脱离了 Thread 继承体系,更灵活。通过查看源码可以发现,方法二其实到底还是通过方法一执行的!

需要注意的是:

  • 如果直接运行Thread的run()方法,则是主线程调用
方法三,FutureTask 配合 Thread

FutureTask 能够接收 Callable 类型的参数,用来处理有返回结果的情况 Test3.java

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        // 实现多线程的第三种方法可以返回数据也可以抛出异常,返回的数据需要用get接收
        FutureTask futureTask = new FutureTask<>(new Callable<Integer>() {
            @Override
            public Integer call() throws Exception {
                log.debug("多线程任务");
                Thread.sleep(100);
                return 100;
            }
        });
        
  
        new Thread(futureTask,"我的名字").start();
        log.debug("主线程");
        //{}表示占位,实际值是后买你的参数,获取结果。必要时可以通过get方法获取执行结果,该方法会阻塞直到任务返回结果。
        log.debug("{}",futureTask.get());
    }

Future就是对于具体的Runnable或者Callable任务的执行结果进行取消、查询是否完成。

public interface Future<V> {
    boolean cancel(boolean mayInterruptIfRunning);
    boolean isCancelled();
    boolean isDone();
    V get() throws InterruptedException, ExecutionException;
    V get(long timeout, TimeUnit unit)
        throws InterruptedException, ExecutionException, TimeoutException;
}

Future提供了三种功能:

  1. 判断任务是否完成;
  2. 能够中断任务;
  3. 能够获取任务执行结果。

3.3 查看进程线程的方法

windows

任务管理器可以查看进程和线程数,也可以用来杀死进程

tasklist 查看进程

taskkill 杀死进程

tasklist | findstr java 查看所有的java线程

linux

ps -fe 查看所有进程

ps -fT -p <PID> 查看某个进程(PID)的所有线程

kill 杀死进程

top 按大写 H 切换是否显示线程

top -H -p <PID> 查看某个进程(PID)的所有线程

ps -fe | grep java 查看所有的java进程

Java

jps 命令查看所有 Java 进程

jstack <PID> 查看某个 Java 进程(PID)的所有线程状态

jconsole 来查看某个 Java 进程中线程的运行情况(图形界面)

jconsole 远程监控配置

需要以如下方式运行你的 java 类

java -Djava.rmi.server.hostname=`ip地址` -Dcom.sun.management.jmxremote -
Dcom.sun.management.jmxremote.port=`连接端口` -Dcom.sun.management.jmxremote.ssl=是否安全连接 -
Dcom.sun.management.jmxremote.authenticate=是否认证 java类

修改 /etc/hosts 文件将 127.0.0.1 映射至主机名

如果要认证访问,还需要做如下步骤

复制 jmxremote.password 文件

修改 jmxremote.password 和 jmxremote.access 文件的权限为 600 即文件所有者可读写

连接时填入 controlRole(用户名),R&D(密码)

例子:

QQ截图20220121153824

QQ截图20220121153952

3.2 线程运行原理

3.2.1.虚拟机栈与栈帧

QQ截图20220121155442

拟机栈描述的是Java方法执行的内存模型:每个方法被执行的时候都会同时创建一个栈帧(stack frame)用于存储局部变量表、操作数栈、动态链接、方法出口等信息,是属于线程的私有的。当java中使用多线程时,每个线程都会维护它自己的栈帧!每个线程只能有一个活动栈帧,对应着当前正在执行的那个方法

3.2.2.线程上下文切换(Thread Context Switch)

因为以下一些原因导致 cpu 不再执行当前的线程,转而执行另一个线程的代码

  • 线程的 cpu 时间片用完(每个线程轮流执行,看前面并行的概念)
  • 垃圾回收
  • 有更高优先级的线程需要运行
  • 线程自己调用了 sleepyieldwaitjoinparksynchronizedlock 等方法

当 Context Switch 发生时,需要由操作系统保存当前线程的状态,并恢复另一个线程的状态,Java 中对应的概念 就是程序计数器(Program Counter Register),它的作用是记住下一条 jvm 指令的执行地址,是线程私有的.

3.3 Thread的常见方法

20200306114615-258720

QQ截图20220121184804

3.3.1 start 与 run

调用start
    public static void main(String[] args) {
        Thread thread = new Thread(){
          @Override
          public void run(){
              log.debug("我是一个新建的线程正在运行中");
              FileReader.read(fileName);
          }
        };
        thread.setName("新建线程");
        thread.start();
        log.debug("主线程");
    }

输出:程序在 t1 线程运行, run()方法里面内容的调用是异步的 Test4.java

11:59:40.711 [main] DEBUG com.concurrent.test.Test4 - 主线程
11:59:40.711 [新建线程] DEBUG com.concurrent.test.Test4 - 我是一个新建的线程正在运行中
11:59:40.732 [新建线程] DEBUG com.concurrent.test.FileReader - read [test] start ...
11:59:40.735 [新建线程] DEBUG com.concurrent.test.FileReader - read [test] end ... cost: 3 ms
调用run

将上面代码的thread.start();改为 thread.run();输出结果如下:程序仍在 main 线程运行, run()方法里面内容的调用还是同步的

12:03:46.711 [main] DEBUG com.concurrent.test.Test4 - 我是一个新建的线程正在运行中
12:03:46.727 [main] DEBUG com.concurrent.test.FileReader - read [test] start ...
12:03:46.729 [main] DEBUG com.concurrent.test.FileReader - read [test] end ... cost: 2 ms
12:03:46.730 [main] DEBUG com.concurrent.test.Test4 - 主线程
小结

直接调用 run() 是在主线程中执行了 run(),没有启动新的线程使用的是main线程, 使用 start() 是启动新的线程,通过新的线程间接执行 run()方法 中的代码

3.3.2 sleep 与 yield

sleep

QQ截图20220121161549

  1. 调用 sleep 会让当前线程从 Running 进入 Timed Waiting 状态(阻塞)
  2. 其它线程可以使用 interrupt 方法打断正在睡眠的线程,那么被打断的线程这时就会抛出 InterruptedException异常【注意:这里打断的是正在休眠的线程,而不是其它状态的线程】
  3. 睡眠结束后的线程未必会立刻得到执行(需要分配到cpu时间片)
  4. 建议用 TimeUnit 的 sleep() 代替 Thread 的 sleep()来获得更好的可读性

小知识:TimeUint的sleep()

yield
  1. 调用 yield 会让当前线程从Running 进入 Runnable 就绪状态,然后调度执行其它线程
  2. 具体的实现依赖于操作系统的任务调度器(就是可能没有其它的线程正在执行,虽然调用了yield方法,但是也没有用)

3.3.3.线程优先级

  • 线程优先级提示(hint)调度器优先调度该线程,但它仅仅是一个提示,调度器可以忽略它, 如果 cpu 比较忙,那么优先级高的线程会获得更多的时间片,但 cpu 闲时,优先级几乎没作用
  • 对应的操作
thread1.setPriority(Thread.MAX_PRIORITY); //设置为优先级最高

3.3.4. join方法

  • 主线程中调用t1.join,则主线程等待t1线程执行完之后继续执行
private static void test1() throws InterruptedException {
    log.debug("开始");
    Thread t1 = new Thread(() -> {
        log.debug("开始");
        sleep(1);
        log.debug("结束");
        r = 10;
    },"t1");
    t1.start();
    // t1.join(); 
    // 这里如果不加t1.join(), 此时主线程不会等待t1线程给r赋值, 主线程直接就输出r=0结束了
    // 如果加上t1.join(), 此时主线程会等待到t1线程执行完才会继续执行.(同步), 此时r=10;
    log.debug("结果为:{}", r);
    log.debug("结束");
}

图示如下:

52ed0d839807dfa6768787cfe659fb9e

思考:等待多个结果时的运行时间’

static int r1 = 0;
static int r2 = 0;
public static void main(String[] args) throws InterruptedException {
 test2();
}
private static void test2() throws InterruptedException {
 //线程t1
 Thread t1 = new Thread(() -> {
 sleep(1);
 r1 = 10;
 });
 //线程t2   
 Thread t2 = new Thread(() -> {
 sleep(2);
 r2 = 20;
  });
    
 long start = System.currentTimeMillis();
 t1.start();
 t2.start();
 t1.join();
 t2.join();
 long end = System.currentTimeMillis();
 log.debug("r1: {} r2: {} cost: {}", r1, r2, end - start);
}

因为线程t1等待时间示1ms,线t2等待时间为2ms,线程t1运行结束后还要等待1ms,线程t2才结束。总共运行2ms,输出。

如图:

QQ截图20220126183826

而调换之后:

static int r1 = 0;
static int r2 = 0;
public static void main(String[] args) throws InterruptedException {
 test2();
}
private static void test2() throws InterruptedException {
 //线程t1
 Thread t1 = new Thread(() -> {
 sleep(1);
 r1 = 10;
 });
 //线程t2   
 Thread t2 = new Thread(() -> {
 sleep(2);
 r2 = 20;
  });
    
 long start = System.currentTimeMillis();
 t1.start();
 t2.start();
 t2.join();
 t1.join();
 long end = System.currentTimeMillis();
 log.debug("r1: {} r2: {} cost: {}", r1, r2, end - start);
}

线程t2join结束后,能立马输出,总时间还是两秒。

QQ截图20220126183947

join()函数里面的参数

同时,join()里还可以写入参数,

  • 当参数小于实际运行时间,主线程等待参数时间,再开始行动

    static int r1 = 0;
    static int r2 = 0;
    public static void main(String[] args) throws InterruptedException {
     test3();
    }
    public static void test3() throws InterruptedException {
     Thread t1 = new Thread(() -> {
     sleep(2);
     r1 = 10;
     });
     long start = System.currentTimeMillis();
     t1.start();
     // join结束,等待结束
     t1.join(1500);
     long end = System.currentTimeMillis();
     log.debug("r1: {} r2: {} cost: {}", r1, r2, end - start);
    }
    
  • 当参数大于实际运行时间,主线程会依照实际运行时间。

static int r1 = 0;
static int r2 = 0;
public static void main(String[] args) throws InterruptedException {
 test3();
}
public static void test3() throws InterruptedException {
 Thread t1 = new Thread(() -> {
 sleep(2);
 r1 = 10;
 });
 long start = System.currentTimeMillis();
 t1.start();
 //运行结束,等待结束
 t1.join(3000);
 long end = System.currentTimeMillis();
 log.debug("r1: {} r2: {} cost: {}", r1, r2, end - start);
}

3.3.5. interrupt

interrupt是特有的打断方法,本身并不会终止线程运行,常常和打断标记配合使用,使得线程终止更加“优雅”。

  • interrupt打断正在运行中的线程时,会让打断标记变为true
  • 打断sleep状态的线程,会报出对应的异常,不会把打断标记变为false

打断正在sleep的线程

private static void test1() throws InterruptedException {
 Thread t1 = new Thread(()->{
 sleep(1);
 }, "t1");
 t1.start();
 sleep(0.5);
 t1.interrupt();
 log.debug(" 打断状态: {}", t1.isInterrupted());
}

输出

java.lang.InterruptedException: sleep interrupted
 at java.lang.Thread.sleep(Native Method)
 at java.lang.Thread.sleep(Thread.java:340)
 at java.util.concurrent.TimeUnit.sleep(TimeUnit.java:386)
 at cn.itcast.n2.util.Sleeper.sleep(Sleeper.java:8)
 at cn.itcast.n4.TestInterrupt.lambda$test1$3(TestInterrupt.java:59)
 at java.lang.Thread.run(Thread.java:745)
21:18:10.374 [main] c.TestInterrupt - 打断状态: false

打断正在运行的线程

private static void test2() throws InterruptedException {
 Thread t2 = new Thread(()->{
 while(true) {
 Thread current = Thread.currentThread();
 boolean interrupted = current.isInterrupted();
 if(interrupted) {
 log.debug(" 打断状态: {}", interrupted);
 break;
 }
 }
 }, "t2");
 t2.start();
 sleep(0.5);
 t2.interrupt();
}
20:57:37.964 [t2] c.TestInterrupt - 打断状态: true

注意:isInterrupted和interrupted的区别

前者将打断标记变为true之后不将它自动变为false 而后者自动将它变为false

3.4.终止模式之两阶段终止模式(一)用打断方式实现

两阶段终止模式就源于堆打断方法和打断标记的利用

大致操作如下图:

QQ截图20220126185229

简单来说就是:用一个监控线程监控所有线程,运行过程中时刻检测当前线程的打断标志是否为true,当打断标志为true时,停止线程。

而我们可以通过此来停止该线程。

当前线程正常运行时被打断可以得到上面我们说的结果,而睡眠中被打断,需要我们手动将标志改为true.

实际代码如下:

public class Test7 {
	public static void main(String[] args) throws InterruptedException {
		Monitor monitor = new Monitor();
		monitor.start();
		Thread.sleep(3500);
		monitor.stop();
	}
}

class Monitor {

	Thread monitor;

	/**
	 * 启动监控器线程
	 */
	public void start() {
		//设置线控器线程,用于监控线程状态
		monitor = new Thread() {
			@Override
			public void run() {
				//开始不停的监控
				while (true) {
                    //判断当前线程是否被打断了
					if(Thread.currentThread().isInterrupted()) {
						System.out.println("处理后续任务");
                        //终止线程执行
						break;
					}
					System.out.println("监控器运行中...");
					try {
						//线程休眠
						Thread.sleep(1000);
					} catch (InterruptedException e) {
						e.printStackTrace();
						//如果是在休眠的时候被打断,不会将打断标记设置为true,这时要重新设置打断标记
						Thread.currentThread().interrupt();
					}
				}
			}
		};
		monitor.start();
	}

	/**
	 * 	用于停止监控器线程
	 */
	public void stop() {
		//打断线程
		monitor.interrupt();
	}
}

3.5打断 park 线程

打断 park 线程是一种将当前线程停止在park()那行的一种方法,可以由打断标志控制,当打断标志为truepark()失去它的作用,false时生效

private static void test3() throws InterruptedException {

Thread t1 = new Thread(() -> { log.debug("park..."); 

LockSupport.park(); log.debug("unpark..."); 

log.debug("打断状态:{}", Thread.currentThread().isInterrupted()); }, "t1"); 

t1.start(); sleep(0.5); 

t1.interrupt();
}

如果不手动复原被打断的线程不会自己复原打断标志,isInterrupted()方法不会自动复原,所以这时我们可以使用 Thread.interrupted() 清除打断状态。

3.6.不推荐使用的方法

QQ截图20220126190228

3.7. 主线程与守护线程

默认情况下,Java 进程需要等待所有线程都运行结束,才会结束。有一种特殊的线程叫做守护线程,只要其它非守护线程运行结束了,即使守护线程的代码没有执行完,也会强制结束。

log.debug("开始运行...");

Thread t1 = new Thread(() -> {
 log.debug("开始运行...");
 sleep(2);
 log.debug("运行结束...");
}, "daemon");

// 设置该线程为守护线程
t1.setDaemon(true);

t1.start();

sleep(1);
log.debug("运行结束...");
//结果
08:26:38.123 [main] c.TestDaemon - 开始运行... 
08:26:38.213 [daemon] c.TestDaemon - 开始运行... 
08:26:39.215 [main] c.TestDaemon - 运行结束...

注意

垃圾回收器线程就是一种守护线程

Tomcat 中的 Acceptor 和 Poller 线程都是守护线程,所以 Tomcat 接收到 shutdown 命令后,不会等待它们处理完当前请求

3.8 五种状态

操作系统的层面上,我们可以把线程的运行分为五种状态:

QQ截图20220126190645

3.9.六种状态

按照线程state()里的划分,我们可以把线程分成六种状态

QQ截图20220126190800

对六种状态的测试:

@Slf4j(topic = "c.TestState")
public class TestState {
    public static void main(String[] args) throws IOException {
        Thread t1 = new Thread("t1") {	// new 状态
            @Override
            public void run() {
                log.debug("running...");
            }
        };

        Thread t2 = new Thread("t2") {
            @Override
            public void run() {
                while(true) { // runnable 状态

                }
            }
        };
        t2.start();

        Thread t3 = new Thread("t3") {
            @Override
            public void run() {
                log.debug("running...");
            }
        };
        t3.start();

        Thread t4 = new Thread("t4") {
            @Override
            public void run() {
                synchronized (TestState.class) {
                    try {
                        Thread.sleep(1000000); // timed_waiting 显示阻塞状态
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        };
        t4.start();

        Thread t5 = new Thread("t5") {
            @Override
            public void run() {
                try {
                    t2.join(); // waiting 状态
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        };
        t5.start();

        Thread t6 = new Thread("t6") {
            @Override
            public void run() {
                synchronized (TestState.class) { // blocked 状态
                    try {
                        Thread.sleep(1000000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        };
        t6.start();

        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        log.debug("t1 state {}", t1.getState());
        log.debug("t2 state {}", t2.getState());
        log.debug("t3 state {}", t3.getState());
        log.debug("t4 state {}", t4.getState());
        log.debug("t5 state {}", t5.getState());
        log.debug("t6 state {}", t6.getState());
    }
}

并发编程核心

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

黑马程序员并发编程笔记(二)--java线程基本操作和理解 的相关文章

  • HTTP 状态 404 - 请求的资源不可用

    在使用 MyEclipse IDE 中的 Tomcat 服务器和 Struts 2 框架时 我遇到了反复出现的问题 我将我的程序作为服务器应用程序运行 当它运行时 默认的index jsp 文件将成功打开 但应用程序的其他过去都不起作用 当
  • java中的csv到pdf文件

    我正在尝试获得一个csv文件解析为pdf 到目前为止我所拥有的内容附在下面 我的问题是这段代码最终出现在 pdf 中的文件在 csv 文件的第一行被截断 我不明白为什么 附示例 本质上我想要一个没有任何操作的 csv 文件的 pdf 版本
  • JTree 节点不会被直观地选择

    不知何故 我无法为我的 JTree 节点启用 选择突出显示 我正在我的项目中使用自定义单元格渲染器 这很可能导致此问题 这是完整的渲染器类代码 protected class ProfessionTreeCellRenderer exten
  • 方法断点可能会大大减慢调试速度

    每当向方法声明行添加断点 在 Intellij IDEA 或 Android Studio 中 时 都会出现一个弹出窗口 方法断点可能会大大减慢调试速度 为什么会这样戏剧性地减慢调试速度 是我的问题吗 将断点放在函数的第一行有什么不同 Th
  • Spring Stomp over Websocket:流式传输大文件

    我的SockJs客户端在网页中 发送帧大小为16K的消息 消息大小限制决定了我可以传输的文件的最大大小 以下是我在文档中找到的内容 Configure the maximum size for an incoming sub protoco
  • 使用 Java 在浏览器中下载 CSV 文件

    我正在尝试在 Web 应用程序上添加一个按钮 单击该按钮会下载一个 CSV 文件 该文件很小 大小仅约 4KB 我已经制作了按钮并附加了一个侦听器 文件也准备好了 我现在唯一需要做的就是创建单击按钮时下载 csv 文件的实际事件 假设 fi
  • cucumber-junit-platform-engine 中的功能文件发现

    In cucumber junit我使用的库 CucumberOptions定义功能文件位置 package com mycompany cucumber import cucumber api CucumberOptions import
  • 使用 java 按电子邮件发送日历邀请

    我正在尝试使用 java 发送每封电子邮件的日历邀请 收件人收到电子邮件 但不会显示接受或拒绝的邀请 而是将该事件自动添加到他的日历中 我正在使用 ical4j jar 构建活动 邀请 private Calendar getInvite
  • @EnableTransactionManagement 的范围是什么?

    我试图了解正确的放置位置 EnableTransactionManagement多个 JavaConfig 上下文的情况下的注释 考虑以下场景 我在 JPAConfig java 和 AppConfig java 中有 JPA 配置以及一组
  • 打印包含 JBIG2 图像的 PDF

    请推荐一些库 帮助我打印包含 JBIG2 编码图像的 PDF 文件 PDFRenderer PDFBox别帮我 这些库可以打印简单的 PDF 但不能打印包含 JBIG2 图像的 PDF PDFRenderer尝试修复它 根据 PDFRedn
  • 为什么 ConcurrentHashMap::putIfAbsent 比 ConcurrentHashMap::computeIfAbsent 更快?

    使用 ConcurrentHashMap 我发现computeIfAbsent 比putIfAbsent 慢两倍 这是简单的测试 import java util ArrayList import java util List import
  • 覆盖 MATLAB 默认静态 javaclasspath 的最佳方法

    MATLAB 配置为在搜索用户可修改的动态路径之前搜索其静态 java 类路径 不幸的是 静态路径包含相当多非常旧的公共库 因此如果您尝试使用新版本 您可能最终会加载错误的实现并出现错误 例如 静态路径包含 google collectio
  • 在 AKKA 中,对主管调用 shutdown 是否会停止其监督的所有参与者?

    假设我有一位主管连接了 2 位演员 当我的应用程序关闭时 我想优雅地关闭这些参与者 调用supervisor shutdown 是否会停止所有参与者 还是我仍然需要手动停止我的参与者 gracias 阻止主管 https github co
  • 如何为 Jackson 编写一个包罗万象的(反)序列化器

    当您提前知道类型时 编写自定义序列化器非常容易 例如 MyType一个人可以写一个MyTypeSerializer extends StdSerializer
  • struts 教程或示例

    我正在尝试在 Struts 中制作一个登录页面 这个想法是验证用户是否存在等 然后如果有错误 则返回到登录页面 错误显示为红色 典型的登录或任何表单页面验证 我想知道是否有人知道 Struts 中的错误管理教程 我正在专门寻找有关的教程 或
  • Path2D 上的鼠标指针检测

    我构建了一个Path2D http docs oracle com javase 7 docs api java awt geom Path2D html表示由直线组成的未闭合形状 我希望能够检测何时单击鼠标并且鼠标指针靠近路径 在几个像素
  • 如何将实例变量传递到 Quartz 作业中?

    我想知道如何在 Quartz 中外部传递实例变量 下面是我想写的伪代码 如何将 externalInstance 传递到此作业中 public class SimpleJob implements Job Override public v
  • Java中获取集合的幂集

    的幂集为 1 2 3 is 2 3 2 3 1 2 1 3 1 2 3 1 假设我有一个Set在爪哇中 Set
  • 为什么 BufferedWriter 不写入文件?

    我有这个代码 String strings Hi You He They Tetrabenzene Caaorine Calorine File file new File G words txt FileWriter fWriter Bu
  • 尝试使用带有有效购买令牌的 Java Google Play Developer API v3 检索应用内购买信息时出现错误请求(无效值)

    当使用 Java Google Play Developer API 版本 3 并请求有效购买令牌的购买信息时 我收到以下异常 API 调用返回 400 Bad Request 响应以及以下消息 code 400 errors domain

随机推荐

  • HTML期末作业-网上书城网上书店

    HTML期末作业 网上书城网上书店 HTML css JavaScript 7个页面 部分源码
  • 史上最强,Jenkins插件实现多个Job并行后再触发Job详细,一篇贯通...

    目录 导读 前言 一 Python编程入门到精通 二 接口自动化项目实战 三 Web自动化项目实战 四 App自动化项目实战 五 一线大厂简历 六 测试开发DevOps体系 七 常用自动化测试工具 八 JMeter性能测试 九 总结 尾部小
  • 【面试】数据仓库面试经验总结

    目录 第一部分 自我介绍 第二部分 专业知识细问 第三部分 数据治理 第四部分 开发 代码能力 第五部分 个人性格测试 第一部分 自我介绍 通常面试官会让进行自我介绍 加项目经历介绍 大多数会按简历上的内容逐条细问 回答的时候尽量根据STA
  • VMWare15.5安装CentOS7.9

    一 创建虚拟机 创建虚拟机 选择自定义 高级 点击下一步 选择默认 点击下一步 选择 稍后安装操作系统 点击下一步 选择要安装的操作系统和版本 点击下一步 修改虚拟机名称和安装路径 点击下一步 根据需要设置处理器数量和内核数量 点击下一步
  • 006.设计原则与思想:规范与重构

    规范与重构 一 理论一 什么情况下要重构 到底重构什么 又该如何重构 1 重构的目的 为什么要重构 why 2 重构的对象 到底重构什么 what 3 重构的时机 什么时候重构 when 4 重构的方法 又该如何重构 how 二 理论二 为
  • elasticsearch-分词测试

    分词结果 tokens token 今天天气 start offset 0 end offset 4 type CN WORD position 0 token 今天 start offset 0 end offset 2 type CN
  • Android架构——ViewModel原理学习总结

    本文是楼主学习ViewModel 源码的一些总结 感觉ViewModel的源码是Android 三大架构中 最容易理解的一个了 本文ViewModel基于版本androidx lifecycle lifecycle viewmodel 2
  • Java - 表达数值的字符串(剑指offer)

    请实现一个函数用来判断字符串是否表示数值 包括整数和小数 例如 字符串 100 5e2 123 3 1416 和 1E 16 都表示数值 但是 12e 1a3 14 1 2 3 5 和 12e 4 3 都不是 剑指offer public
  • 100个Python小游戏,上班摸鱼我能玩一整年【附源码】

    哈喽铁子们 表弟最近在学Python 总是跟我抱怨很枯燥无味 其实 他有没有认真想过 可能是自己学习姿势不对 比方说 可以通过打游戏来学编程 今天给大家分享100个Python小游戏 一定要收藏 相关文件代码已上传 文末扫一下名片备注 游戏
  • Kettle实例-缺失值处理-去除缺失值

    1 通过使用Kettle工具 创建一个转换delete missing value 并添加 文本文件输入 控件 字段选择 控件 过滤记录 控件 Excel输出 控件 空操作 什么也不做 控件以及Hop跳连接线 2 单击 浏览 按钮 选择要去
  • 多线程(一):通俗易懂的理解线程和进程

    目录 计算机常识 什么是程序 什么是进程 什么是线程 如果理解线程切换 程序和CPU的常识 线程切换过程 普及几个线程面试题 和以上说过的知识相关 1 单核CPU设定多线程是否有意义 2 工作线程数是不是设置越大越好 3 工作线程数 线程池
  • echarts自定义多根柱子在一起柱状图/条形图

    先看效果 与单一柱状图相比 多柱子的多定义了几个series的值 legend值 注意的是 这东西叫图例标记 是legend下面的参数 看代码 div style width 100 height 240px div
  • 史上最全的java随机数生成算法(转)

    转自 http www zuidaima com share 1585762703215616 htm package com test util import java util Random public class RandomUti
  • 关于elasticsearch与kibana、IK分词器

    初识elasticsearch 正向索引和倒排索引 什么是文档和词条 每一条数据就是一个文档 对文档中的内容分词 得到的词语就是词条 elasticsearch就是面对文档存储的 可以是数据库中的一条商品数据 一个订单信息 文档数据会被反序
  • 找出字符串中第一次出现一次的字符的算法。

    链接 https www nowcoder com questionTerminal d370c322d06945a5901e8436d1e2e681 orderByHotValue 1 page 1 onlyReference false
  • 我为什么要学习Rust

    最早接触到 Rust 是在几年前的一次技术大会上 黄东旭说 TiKV 是用 Rust 语言编写的 引起了我的一些兴趣 但只是保持关注而已 我一直认为每一种编程语言都有着各自的典型应用领域 也有着各自的编程范式 没有最好的编程语言 参见 PH
  • 不讲武德---不用代码爬虫

    有人问 我不会代码 我能爬虫吗 我 很快啊 回答 可以 不需要写代码的 那当然是需要工具了 较为熟知的爬虫工具有八爪鱼 和web scraper 这次我所使用的是web scraper 安装web scraper 这篇文章讲述的算清晰的了
  • JetBrains插件推荐

    JetBrains软件本身就是效率神器 配合上一些好用的插件 效率就更是飞升了 本文就简单记录一些好用的插件和简介 持续更新 安装方法都很简单 这里就不过多叙述了 实在不会就百度一下 Chinese Simplified Language
  • smb windows中使用的文件共享协议(主要用于与windows互通)

    主要是samba服务 SMB协议又成为CIFS Common Internet File System 协议 samba服务功能 1文件共享 2打印共享 3加入windows2000 2003 2008域环境 4通过windows域环境进行
  • 黑马程序员并发编程笔记(二)--java线程基本操作和理解

    3 java进程的基本操作 3 1 创建进程 方法一 直接使用 Thread 构造方法的参数是给线程指定名字 推荐给线程起个名字 用setName 也可以 Thread t1 new Thread t1 Override run 方法内实现