【高级网络程序设计】Block1总结

news2024/12/23 0:36:52

        这一个Block分为四个部分,第一部分是Introduction to Threads and Concurrency ,第二部分是Interruptting and Terminating a Thread,第三部分是Keep Threads safety:the volatile variable and locks,第四部分是Beyond simple locks:the monitor。

      第一部分:Introduction to Threads and Concurrency

        在这一部分中,首先介绍了Processes and Threads,然后讲了如何create a thread,接着说明了一些关于thread的方法,用来control your thread and coordinate your thread.

        1.  Processes and Threads

        关于Processes and Threads,我们首先用一张relative drawing直观的看出它们之间的关系,然后以JVM is a process来引出process与上图呼应,接着介绍了thread和process的区别,最后讲了在concurrent programming里面的四个重要概念。

        ① relative drawing

        ② JVM is a process

        与上图相对应,我们可以知道:a java application runs by default in a process; work with several threads to achieve psedo parallel process / asychronous behaviour.

        ③ Processes and Threads

        从四个方面来介绍进程和线程,运行独立,访问,资源分配

Processes Threads
run independently from othersa lightweight process, has its own call stack
cannot access data in other processescan access shares data of threads in the same process
the resources are allocated via the operating systemhas its own memory cache, reads shared data, store it and re-read the data

     ④ The key concepts in concurrent programming

        在并行编程中,有四个关键的概念:原子性,可见性,运行顺序和关键代码。

        原子性(atomicty)指的是不能再进行分割的代码,即:when it cannot be interrupted。一旦开始运行就结束了,即:once it starts it always complete。最典型的例子就是a++的非原子性,除此之外,X = new Integer(x)(create-assign the reference)、x = y(将y的值赋值给x read-write)、x.equals(y);(比较x和y的值是否相等)均为非原子操作,他们都是多个步骤。常见的原子操作有x=3这种简单的基本数据类型的赋值。【关于原子性,在后面的第三部分volatile variable会提到,原子性也是可以使用volatile的条件】

        可见性(visibility)指的是再此线程运行的时候必须看到其他线程的运行,即:when a thread must watch the actions of another thread。典型的例子是线程的终止,数值的设定。

        运行顺序(the order of execution),关于运行顺序,正常程序是run in the same order everytime,并行程序是the order of execution is never guaranteed。对于这个概念,可以出相关考题,给出一段多个线程的代码,判断输出,这时候运行顺序是不确定的,输出也是不确定的。

        关键代码(critical code)指的是只能由一个线程执行一次的代码部分,即:a part of code that only can be executed by a single thread at one time。【关于关键代码,在后面第三部分volatile variable中会再次出现,不同的是提出的是关键部分critical section】

        2. create a thread

        ① The thread class

        提到线程类(thread class),它的作用是executing your stuff in a thread,那stuff 在哪儿呢,your stuff is encapsulated in a run() method

       关于创建线程,我们有两种方式——使用implements Runnable和使用extends Thread,具体来说是:pass your class into a new Thread object,extend the Thread class

        Thread我们很熟悉了,是线程类,那Runnable是什么呢——Runnable is an interface that requires you to implement a run() method.

         因此,对于一个线程类,我们首先要implement/extend,然后写两个函数,一个是public void run(),一个是public static void main(String[] args)。

        ② Implements Runnable / extends Thread

        Implement Runnable 和 extend Thread除了在类名后面的内容上有所不同之外,在线程的创建上也有所不同。下面将解释一下:

public Order implements Runnablepublic Order extends Thread

Order order  = new Order();

Thread t1 = new Thread(order);

Order t1  = new Order();

         关于两种方式,更好的是Implements Runnable,因为Implements Runnable allows a subclass of Thread to be used if required,然而extends Thread——no other classes can be inherited by MyThread.

        3. control your thread

        ① 控制线程-sleep(), yield()

       关于控制线程,包括make your thread sleep interrupt your thread's sleep。完成这两个任务,我们需要去 make the code to execute at the appropriate time manage resource,一是时间二是资源。

        这里我们将介绍三种方法——sleep(), yield(), interrupt()以及interrupt的相关运作机制(InterrupedException,InterruptFlag,使用Interupt的反应和使用Interupt的情况)

        sleep():static method。它的作用是make the current thread sleep。使用之后它的结果是the thread will pause and will free up CPU for other threads

        yield():static method。它的结果是the executing thread is suspended and the CPU is given to other runnable thread。换一种说法是the executing thread is returned to the ready queue of the processor and wait for its next turn

        ② interrupt()

        在程序运行中会发生线程的blocka thread if prevented from doing anything),原因可能是waiting for a monitor lock 或者时suspended by call to wait()[become runnable on a notify/ notifyAll]。【Block发生的原因】

       那么当我们遇到block的时候如何处理呢——interrupt()!【使用Interupt的情况】

        interrupt():non-static method。当使用它的时候需要用t1.interrupt()/Thread.current Thread().interrupt(),那么在使用之后会发生什么呢?【interrupt()】

        分为两种情况,第一种是当线程sleep的时候,第二种是线程没有sleep的时候。sleep时,进行interrupt,首先会将interrupt flag中断标记设为true,然后会throw InterruptedException,同时会clear the interrupt flag清除中断标记;没有sleep时,进行interrupt,只会将interrupt flag中断标记设为true。【使用Interupt的反应】

        什么是InterruptedException,什么是interrupt flag中断标记呢?

        InterruptedException,会在the thread is interrupted while sleeping的时候发生,作用是enable you to deal with interrupt elegantly. 在try...catch(InterruptedException e){e.printStackTrace()}语句中进行使用。【InterrupedException】

        interrupt flag,存在于every Thread object,为了标记中断会change this flag to true。如果值为true时,需要finish the method immediatly;如果值为false,continual as normal。当然这也是建立在是否为sleep state的基础上。interrupt flag

        4. coordinate your thread

        对于协调线程,我们需要用到join()方法:non-static method。它的作用时pause util the other thread has terminated(use on any thread to wait for it to die),跟sleep一样,需要用到InterruptException

        第二部分:Interrupting and Terminating threads

        1. Interrupting threads

       关于中断线程,我们分为三个部分进行讲解——中断的概念,中断机制和判断线程是否中断的方法。

        ① Interrupt

        Interrupt(中断)an indication to a thread that it should stop what it is doing and do something else.(not stop the thread)。那我们如何使其停止呢?——The programmer decides how a thread responds to a thread。也就是说,首先需要进行中断(A thread sends an Interrupt by invoking interrupt() on the Thread object to be interrupted),然后再根据programmer指示去做,这个过程我们需要Interrupt mechenism的支持。【interrupt的概念、使用】

        ② Interrupt mechanism

        Interrupt mechanism的实现离不开中断标记(Interrupt flag/interrupt status)。对于中断标记的设置,我们需要用到Interrupt()函数,对于中断标记的检查,我们可以用两个方法——interrupted()和isInterrupted()

        ③ Interrupt methods

       下面我们将从类型、作用和特点三个方面来讲述两者的区别

Thread.interrupted()

t1. isInterrupted()
staticnon-static
check the current threadcheck the Thread object that it is called on
clear the status of the current thread/

        2. Terminating threads

        上一章节,我们提到了Exception,关于为什么使用Exception,我们有两种解释——deal with an unusual situation, elegantly finish whatever we are doing.但是终止结束线程,首先要保证线程是alive的,然后再进行终止方法的选择。

        ① IsAlive()

        线程alive指的是when it has been started and is not dead yet。判断线程alive需要用到isAlive()方法,thread is alive——return true。

        ② 3 ways to terminate

        关于终止线程,我们有三种方式,分别是——finish the thread naturally, deamon threads 和interrupt the thread。

        finish the thread naturally有两种情况——doing nothing(start-let it finish)和use a shared Boolean(periodically check to see if pleaseFinish is set to true, true——finish thread)。我们重点注意的是第二种使用Boolean的方式,示例代码如下:

public volatile boolean pleaseFinish = false;

public void finishThreadPlease(){

        pleaseFinish=true;

我们需要注意的是,这个方法使用的有效是存在条件的,即thread需要alive——runnable。non-runnable的时候有以下几种情况——sleep(), wait(), blocking on IO。如果我们想要迅速得到这个线程,可以使用interrupt方法。

        daemon threads也存在两种情况,但是与上述不同的是,它是通过方法setDeamon来设置的——setDeamon(true)和setDeamon(flase)。setDeamon(true)是the thread terminates when the parent thread terminates,setDeamon(false)是the thread continues to run after the parent thread has finished.需要注意的是,需要在线程开始之前进行设置,示例代码如下:

public void run(){

        WorkerThread t1 = new WorkerThread();

        t1.setDeamon(true);

        t1.start();        

}

        第三种方式也是我们熟悉的Interrupt,在此前面的内容不再赘述,就interrupt之后的反应再进行详细讨论。首先,我们需要知道interrupt是an indication并非强制停止,因此it will not automatically stop a thread unless you programme to do so。然后,在线程中断之后,我们需要做出反应,这时需要用到InterruptedException来抛出异常。但是呢,这个异常的抛出只是在sleep()/wait()方法作用之后才会发生,接下来我们就需要用到isInterrupted()和interruted()方法来routinely check for interrupts at strategic points where you can safely stop and cleanup.最后呢,我们再来讨论一下exception的情况,exception被抛出时说明线程是处在sleep()/wait()时,我们知道在exception被抛出之前的时候,sleep会将interrupt status清除——clear the interrupt status。为了重新保存中断状态,我们需要进行在exception的catch语句中重新进行一次中断。示例代码如下:

//InterruptedExcption抛出异常

public void run(){

       //...

        try{

               Thead.sleep(5000);

         }catch(InterruptedException e){

                e.printStackTrace();

        }

}

//restore the interrupt status

public void run(){

        //..

        try{

                Thread.sleep(5000);

        }catch(InterruptedException e){

                e.printStackTrace();

                Thread.currentThread().interrupt();

        }

}

        第三部分:Keep Threads safety:the volatile variable and locks

             当不同的线程访问同一个变量或者是同一个方法的时候,会出现冲突,为了解决变量访问的冲突,我们提出了volatile variable,为了解决方法访问的冲突,我们提出了lock。

        1. Keeping your code safe the volatile keyword 

        ① Thread safe code 

        关于线程安全有两个要点,首先是多线程操作共享数据,然后是不同时进行操作,即manipulate shared data structure in a manner that guarantees safe execution by multiple threads at the same time

        ② volatile

        volatile关键字很重要,没有了volatile关键字,代码就不能正常工作。那volatile有什么用呢?volatile是用来表示变量值会被不同线程修改,即indicate that  a variable's value will be modified by different threads,因此就可以实现变量只会被单线程访问,即access to the variable is only given to one thread at a time。但是并不是所有的变量都可以被volatile进行修饰,当加载、读取、写入等工作在变量上都是atomic的时候,才可以使用。【volatile的概念和特点】

        那我们什么时候不能够或者不需要使用volatile呢?有三种情况,变量为final,变量只会被单一线程访问 by single threadcomplex operation。示例代码如下:【volatile不需要使用的时候】

public class StoppableTask extends Thread{

        private volatile boolean pleaseStop;

        public void run(){

                while(!pleaseStop){// }

        }

        public void tellMeToStop(){

                pleaseStop = true;

        }

}

        ③ Common traps with volatile常见陷阱     

        关于volatile,我们知道使用条件具有原子性,访问具有单一性,因此在使用条件和访问上会有以下常见陷阱:

        如果将数组arr[]声明为volatile,数组的reference(arr)是volatile的,但是individual field accesses(arr[0],arr[1]...)不是thread-safe

        unary operation(++, --) 不是atomic,不是thread-safe>

        在数据访问过程中,我们需要进行变量缓存。但是如果变量被修改了,其他线程的缓存就会过时。因此,变量的值不会被本地缓存,所有的读取和写入都之间到main memory中。即 The value of variables will never be cached thread-locally, all reads and writes will go straight to "main memory"。

        2. Beyond volatile: using locks

        除了变量需要同一时刻被单一线程访问以外,还有代码块也需要如此。但是volatile只能对atomic operation进行操作(本章节只涉及变量——基本变量类型),不能对complex operation进行操作,所以我们需要引入lock。下面将介绍critical section和lock的相关问题,其中对于lock的介绍,我们分为

        ① Critical sections

          我们之前在第一部分提到过critical code的概念,即a part of code that can be executed by a single thread at a time。critical section将引入data和多个分别的并发的线程来进行另一种类似的表述,即 the code segments within a program that access the same data from within seperate, concurrent threads. 这部分critical section需要用synchronized关键词进行修饰,也称作synchronized section。对于synchronized section,只能在给定时刻被单一线程访问,即can only be accessed by a single thread at any given time.【critical section的概念,关键词和特点】

        ② Locks

        关于锁的使用,锁是作用在一个特定的代码部分上面的,即 A lock applies to a particular section of code。当我们使用锁之后,If the code is locked, no other thread can execute it. If the code is unlocked, any thread can take the lock and execute it。【锁的使用和效果】

        关于锁的分类,可以分为内部锁Intrinsic locks 和外部锁Extrinsic locksIntrinsic locks 是 每个对象都可以通过使用sychronized关键词来起到锁的作用。every object can function as a lock that is triggered using the keyword synchronized.

        其中,我们需要注意到锁的线程唯一性

        只有一个线程可以在同一时刻执行这个方法,当一个线程拥有lock时,其他线程不能再获取lock了,必须等到其释放。Only one thread can execute the method at the same time. When a thread has a lock, no other thread can acquire it. It must wait for the first thread to release the lock.

        如果两个方法被sychronized关键词修饰,只有一个可以执行,因为相同锁会被一个对象中的所有方法使用。Two methods with the synchronized keyword, only one method of the two will be executed at the same time. Because the same lock is used for all methods in an object.

        ③ Intrinsic lock 内部锁

         内部锁是每个对象通过使用sychronized关键词来起到锁的作用,那么我们如何来利用到sychronized关键词呢?我们有两种使用方式

        Synchronized methods

protected synchronized int getNextAvailableItem() {
    … return items;

protected int getNextAvailableItem() { 
    synchronized (this){
    … return items; 
    }
}

        如果方法为静态的话,那么使用的锁是Class对象——If the method is static, the used lock is the Class object

        Explicit use of the intrinsic lock(Synchronized statements)

public class Example {
    private int value = 0;
    public int getNextValue() {
        synchronized (this) {
            return value++;
        }
    }
}

        与synchronized methods不同, synchronized statements必须指定提供内部锁的对象——must specify the object that provides the intrinsic lock。通常情况下,关键部分是方法,也可以标记更小段为sychronized——critical sections in Java programs are methods. You can mark smaller code segments as synchronized. 对于大多数的java程序来说,最好再方法水平上使用synchronized。


        ④ Scope of a lock 锁的范围/作用域

        以上,我们讨论了lock的使用和效果——作用域特定的代码块,locked之后无法被执行;然后讨论了lock的分类,重点介绍了intrinsic lock——定义、两种不同的使用方式以及作用水平。现在我们将讨论锁的范围。

        lock的范围是在锁使用和释放之间的时间——The time between when the lock is taken and when the lock is released。那这个时间段是由什么来决定的呢?它是由代码段所决定的——Lock scopes can be determined by segments of code (a method or just a part of code)。再次注意,所作用的对象是对象不是方法——locks apply to objects not methods。并且,锁不是方法而是保护方法的东西—— A lock isn’t a method, it’s something that protects a method。

        ⑤ Full/Partial synchronization 完全同步和部分同步

        完全同步指的是每个方法都同步的类(无公共实例变量)保证了局部顺序行为—— A class in which every method is synchronised (that has no public instance variables) guarantees locally sequential behaviour. 因此,他们在一个时刻制作一件事情——They only do one thing at a time:ready (idle - not having the lock) / active (processing a method) / waiting (for a reply)

        ⑥ 其他

        讨论完完全同步,我们还有部分同步未讨论,现在我们要从方法的调用、方法的执行、方法的本身来进行详细的讨论:

        方法的调用:synchronized方法可调用unsynchronized方法——只有synchronized方法会获取lock,unsynchronized方法不会获取lock,所以可在synchronized方法中调用unsynchronized方法。synchronized方法可以调用另一个synchronized方法——同一object的synchronized方法share the same lock,已经持有lock的线程可继续执行其他synchronized方法,不需重新获取lock。

        方法的执行:标记为synchronized的方法或代码块将完整地执行——除非被wait方法explicitly suspended,否则在synchronized块完成之前,其他线程将被blocked。未被标记为synchronized的方法可以立即执行——即使对象的另一个方法正在执行,甚至是一个同步方法。对于非同步方法,没有要获取的锁,所以它们可以并行执行。

        方法的对象:每个object只有一个lock——每个object都有一个关联的lock,用于实现synchronization。对于static方法,使用的是该class对象的lock。

// 一个non-static方法可以使用代码块锁定静态数据—— 使用类对象作为同步锁
        synchronized (getClass()) {...}


// 只能在对象上进行同步操作,而不能在基本类型变量上进行同步。

synchronized (temp) { temp = 10; }


        方法的实现:lock是一个counter——每当一个thread进入一个synchronized方法或块时,就会增加。如果counter不为0,表示有thread已经持有该lock,当前thread将被阻塞,直到计数器为0。当线程退出synchronized方法或块时,counter会递减。

        方法的继承:synchronized关键字不会自动继承到子类方法中。当重写一个方法时,如果父类的方法被synchronized修饰,子类中覆盖该方法时需显式地加上synchronized,否则子类方法将不会同步

Synchronizedvolatile
method or scope declared synchronized primitive variable declared volatile
A synchronized method can protect more complex code

Access to a volatile variable never has the potential to block 

– Volatile only protects atomic operations

– not suitable for complex operations, a ++

        第四部分:Beyond simple locks:the monitor

        1. Monitor

        在保证线程安全中,我们引入了volatile,作用于变量,保证变量访问的安全性,然后引入了锁,作用于代码块,保证方法(代码块)使用的安全性。但是我们只是简单的让方法与方法之间互斥,并没有使其能够达到合作。因此提出了monitor

        ① From intrinsic locks to monitors

        关于intrinsic lock和monitor,两者之间在使用和作用方面不同。

intrinsic lockmonitor
support Mutual Exclusion through the use of the keyword synchronized  support Cooperation through the wait() & notify() methods
Only allow one thread to execute a part of code at a given time    

Enable threads to work together

(Wait and Notify monitors or Signal and Continue monitors)

        对于内部锁,实现是通过在方法/代码段上使用synchronized关键词,并通过对象调用方法或者在synchronized statement上指定作用对象来实现的。那monitor是如何实现的呢?Every object can be a monitor 。我们还需要三个部分来实现monitor

synchronizedcreates the lock to protect the critical section of the code
wait() on an objectpauses a thread and puts it in a wait set (the set of threads waiting for the lock to become free)
notify() on that objectreawakens a thread from the wait set

        对于Monitor来说,只是 another lock?在原有的基础上,Using the synchronized keyword ensure mutual exclusion—— Only one thread can execute the method at a given time,还添加了功能, allows cooperation between threads—— Allows threads to pause their execution and notify other threads of events.


② Entry set, wait set, owners


        对于这张图,我们可以看出分为左中右三个部分,左边是entry set(enter:进入lock region的线程——需要被放入相关monitor的entry set),中间是lock region/the owner(acquire:执行lock region的线程——没有其他的线程在entry set中等待,当前线程成功地获取了锁),右边是wait set( release and exit : the thread finishes executing the lock region)
          wait set是我们的重点,进入和出去两个途径进行讲述——release和acquire。如何release(进入wait set)呢?A thread that currently owns the lock can suspend itself inside the lock by executing a wait() command,执行wait()后——releases the lock and enters a wait set, the thread will stay suspended in the wait set until another thread executes a notify() command inside the lock。为了从wait set中出去,我们需要用到notify()——When a thread executes a notify, it continues to own the lock until it releases the lock of its own accord, either by executing a wait or by completing the lock region; After the notifying thread has released the lock, the waiting thread will be resurrected and will reacquire the lock.

        Notify 说明哪一组可以竞争—— wait or entry set
        ① If the (former) lock owner did not execute a notify before it released the lock:then only the threads in the entry set will compete to acquire the lock.
        If the (former) lock owner did execute a notify:then the entry set threads will have to compete with one or more threads from the wait set. 
        ② thread wins the competition
        from the entry set , it becomes the new owner of the lock.
        from the wait set wins the competition, it exits the wait set and reacquires the lock.

        A thread can only execute a wait command if it currently owns the lock – i.e., it is currently inside the synchronized block. 

        Notify有两种—— “notify”和“notify all”
        ① notify(): selects one thread arbitrarily from the wait set and marks it for eventual resurrection

        ② notifyAll():marks all threads currently in the wait set for eventual resurrection

        2. Deadlocks

        ① 定义:Two or more threads waiting for two or more locks to be freed, and the circumstances in the program is such that the locks will never be freed

        ② solutions
        • Prevention:Design code so deadlock is impossible

        – Avoid mutual exclusion

        – Allow pre-emption

        – Don’t allow a thread to hold multiple locks

        •  Avoidance:Steer around deadlock with smart scheduling

        • Detection and Recovery:Check for deadlock periodically; Recover by killing threads and restarting Deadlock solutions

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

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

相关文章

RabbitMQ不公平分发问题分析及问题解决

1.不公平分发 1.1 不公平分发策略是什么? 在 RabbitMQ 中,不公平分发(Unfair Dispatch)是指当多个消费者(Consumers)同时订阅同一个队列(Queue)时,消息的分发机制是不公…

把文化注入品牌,五粮液荣获“全国企业文化优秀成果特等奖”

执笔 | 萧 萧 编辑 | 扬 灵 12月15日,以“塑造优秀企业文化,凝聚企业发展力量”为主题的全国企业文化年会(2023)首次在长江首城、中国酒都、中国动力电池之都宜宾盛大举行。 凭借“弘扬和美文化,谱写高质量发展新篇章”成果…

2018年AMC8数学竞赛真题的典型考点和详细解析

从战争中学习战争最有效。前几天,六分成长分析了2023年、2022年、2020、2019年的AMC8的典型考题、考点和详细答案解析。今天继续为大家分享2018年的AMC8的五道典型考题。 欢迎您查看历史文章了解之前各年的真题解析,本系列会持续更新,直到大家…

Linux:进程地址空间

目录 1.程序地址空间 2.进程地址空间 1.程序地址空间 我们在讲C/C语言的时候,32位平台下,我们见过这样的空间布局图 我们来验证一下这张图的正确性: int un_gval;int init_gval100;int main(int argc, char* argv[],char* env[]){//代码…

Nat. Mach. Intell. | 通过深度神经网络联合建模多个切片来构建一个三维全生物体空间图谱

今天为大家介绍的是来自Angela Ruohao Wu 和Can Yang团队的一篇论文。空间转录组学(ST)技术正在革新探索组织空间结构的方式。目前,ST数据分析通常局限于单个二维(2D)组织切片,这限制了我们理解在三维&…

【ArkTS】入门

代码结构分析 struct Index{ } 「自定义组件:可复用的UI单元」 xxx 「装饰器:用来装饰类结构、方法、变量」 Entry 标记当前组件是入口组件(该组件可被独立访问,通俗来讲:它自己就是一个页面)Component 用…

【后端学前端】第四天 css动画 垂直轮播效果(css变量、位移缩放动画、动画延迟)

1、学习信息 视频地址&#xff1a;css动画 垂直轮播效果&#xff08;css变量、位移缩放动画、动画延迟&#xff09;_哔哩哔哩_bilibili 2、源码 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>Title…

QT for Android安卓编译环境搭建+首次编译3个大坑

1、安装 编译环境能否搭建成功&#xff0c;主要是看各个依赖软件的版本是否匹配。依赖的软件有3个&#xff1a;JDK、安卓SDK、安卓NDK。 我的qt版本是5.14.1&#xff0c;我亲测以下版本可以成功让编译安卓&#xff1a; QT5.14 JDK1.8.0 安卓SDK26.1 安卓NDK20.1 在QT-&g…

爬虫 scrapy ——scrapy shell调试及下载当当网数据(十一)

目录 一、scrapy shell 1.什么是scrapy shell&#xff1f; 2.安装 ipython 3.使用scrapy shell 二、当当网案例 1.在items.py中定义数据结构 2.在dang.py中解析数据 3.使用pipeline保存 4.多条管道的使用 5.多页下载 参考 一、scrapy shell 1.什么是scrapy shell&am…

VBA即用型代码手册之工作薄的创建及保存

我给VBA下的定义&#xff1a;VBA是个人小型自动化处理的有效工具。可以大大提高自己的劳动效率&#xff0c;而且可以提高数据的准确性。我这里专注VBA,将我多年的经验汇集在VBA系列九套教程中。 作为我的学员要利用我的积木编程思想&#xff0c;积木编程最重要的是积木如何搭建…

python封装执行cmd命令的方法

一、前置说明 在自动化时&#xff0c;经常需要使用命令行工具与系统进行交互&#xff0c;因此可以使用python封装一个执行cmd命令的方法。 二、代码实现 import subprocess import timefrom common.exception import RunCMDError from common.logger import loggerclass Cmd…

Nat Med | 白血病患儿持续存在CD19 CAR-T细胞的转录特征

今天给同学们分享一篇实验文章“Transcriptional signatures associated with persisting CD19 CAR-T cells in children with leukemia ”&#xff0c;这篇文章发表在Nat Med期刊上&#xff0c;影响因子为82.9。 结果解读&#xff1a; 研究队列和实验概述 作者研究了15例高…

网络编程day2作业

1.tcp实现通信 服务器&#xff1a; //tcp服务端#include <head.h>#define SERPORT 8888 #define IP "192.168.125.6"int main(int argc, const char *argv[]) { //1.创建套接字int sfdsocket(AF_INET,SOCK_STREAM,0);//2.绑定struct sockaddr_in ser;ser.sin…

java --- 集合进阶

目录 一、单列集合顶层接口 Collection 1.1 基本方法 1.2 Collection 的遍历方式 二、list集合 1.2 ArrayList Vector 底层结构 1.3 LinkedList ArrayList 和 LinkedList 比较 三、set接口 3.1、Set 接口和常用方法 3.2 HashSet HashSet 底层机制&#xff08;HashMap…

虚拟机Linux(Centos7)安装Docker

如果没有安装虚拟机的&#xff0c;可以参考这篇VMware虚拟机安装Linux操作系统&#xff08;CentOS7&#xff09; 文章目录 0.安装Docker1.CentOS安装Docker1.1.卸载&#xff08;可选&#xff09;如何看自己的虚拟机上是否安装过docker&#xff1f; 1.2.安装docker1.3.启动docke…

pytest之allure测试报告02:allure具体使用方法

一、allure包含的方法 二、allure使用教程 &#xff08;1&#xff09;用例中写入allure方法 allure.epic("数据进制项目epic") allure.feature("手机号模块feature") class TestMobile:allure.story("杭州的手机号story")allure.title("测…

多层记忆增强外观-运动对齐框架用于视频异常检测 论文阅读

MULTI-LEVEL MEMORY-AUGMENTED APPEARANCE-MOTION CORRESPONDENCE FRAMEWORK FOR VIDEO ANOMALY DETECTION 论文阅读 摘要1.介绍2.方法2.1外观和运动对其建模2.2.记忆引导抑制模块2.3. Training Loss2.4. Anomaly Detection 3.实验与结果4.结论 论文标题&#xff1a;MULTI-LEVE…

重磅!大模型(LLMs)排行榜清单发布!

目前&#xff0c;人工智能领域呈现出一片蓬勃发展的景象&#xff0c;大型模型成为了激发这一繁荣的关键引擎。 国内不仅涌现了众多大模型&#xff0c;而且它们的发展速度之快令人瞩目。这种全面拥抱大型模型的态势为整个人工智能生态系统赋予了新的活力&#xff0c;让我们对国…

栈——OJ题

&#x1f4d8;北尘_&#xff1a;个人主页 &#x1f30e;个人专栏:《Linux操作系统》《经典算法试题 》《C》 《数据结构与算法》 ☀️走在路上&#xff0c;不忘来时的初心 文章目录 一、最小栈1、题目讲解2、思路讲解3、代码实现 二、栈的压入、弹出序列1、题目讲解2、思路讲解…

CCD相机为什么需要积分球均匀光源

积分球内腔是一个具备高漫反射特性的收光球&#xff0c;其内部中空、内球面均匀地涂有漫反射材料&#xff0c;具有匀光与混光的作用&#xff0c;因此常常被用来做收光的均光球。由于光源性能等因素的影响&#xff0c;可能导致出射光线带偏振方向、出光不均匀&#xff0c;使用积…