黑马程序员_多线程(线程安全和通信)

LabVIEW新手必看:5分钟搞定S7-1200 OPC通信(附完整配置截图) 本文详细介绍了LabVIEW与西门子S7-1200 PLC通过OPC通信实现工业监控系统的完整配置流程。从环境准备、PLC数据块配置到OPC Server高级设置,逐步指导新手快速建立稳定通信链路,并分享工业级应用的优化技巧和异常处理方案,帮助用户提升自动化系统集成效率。 阅读详情

------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! ------- 

多线程(线程安全和通信)

一、线程安全问题

线程安全问题,详细来说,先看一个程序。

                            If (tick>0)

                                     System.out.println(Thread.currentThread()+"..sale..."+tick- -);

这是继承了Runnable接口的子类的run方法中的一部分代码。我们知道,CPU在每个时间段,仅会执行一个程序,当我们建立多个线程来运行这一部分代码的时候,问题就发生了。假如有两个线程,线程A和线程B,当线程A执行时,这是tick的值是1,这是可以通过if语句,但是在下一条输出语句之前被暂时冻结了(注意输出语句中的tick执行完就会减1),这时线程B也进来了,但tick还是1,所以也通过if语句了,同时也在输出语句之前冻结了。这个情况之后,CPU回来执行线程A,继续执行下面的输出语句,之后tick的值就变为了0,这时其实这个if语句就该停止了,但是CPU又开始执行线程B了,所以又往下执行了一次输出语句,tick已经变了,所以最后tick编程了-1。这是我们设计程序里不合理的,这就是线程的安全问题。

简单的说:

         当多条语句在操作同一个线程共享数据时,一个线程对多条语句只执行了一部分,还没有执行完,另一线程就参与进来执行,导致线程共享数据错误。

解决办法:

         对多条操作共享数据段语句,只能让一个线程都执行完,在执行过程中,其他线程不可以参与执行。

 

这就引入了同步代码块:

         synchronized(对象)

{ 需要被同步的代码 }

 

同步代码块传入的是对象,注意一般来说只要是对象即可。示例程序如下:

         Object obj = new Object();

synchronized(obj)

{       If (tick>0)

                      System.out.println(Thread.currentThread()+"..sale..."+tick- -);

 }

同步代码块中的对象,就相当于一个锁,当有一个线程进入到这个代码块中,就相当于把这个锁给锁上了,外面进不来,只有当这个线程执行完同步代码块中的程序,才会把这个锁给打开。另一种描述是,进入代码块的线程,持有这个锁,当线程执行完程序后,才会释放这个锁,使得后面的线程可以进入。同步代码块中同一时间只会有一个线程。

 

总结:

1、  多线程存在安全问题,多个线程操作同一条共享数据时会发生错误。

2、  错误原因是:一个线程对多条语句只执行了一部分,这时另一个线程就进来执行,导致线程共享数据错误。

3、  处理多线程安全问题用同步代码块,格式记住了。

4、  同步代码块要注意的是,一、传入的是对象,可以是任意对象。二、代码块中寸放大是需要被同步的代码,不要全部放入。三、同步代码块中仅会有一个线程再执行。

5、 同步的前提:一、必须要有两个或者两个以上的线程。二、必须是多个线程使用同一个锁。

6、 同步代码块的优点:解决了多线程安全问题。弊端:因为多加判断,较为耗费资源。

 

 

二、线程安全的各种情况

我们在写程序时,如果用到线程安全问题,该怎么去判断,怎么去具体的给需要的代码加上同步代码块?

根据我们已学的去判断的话,多线程使用的我们自己定义类中run方法中的程序,这部分程序时我们建立多线程时,线程实际执行的部分,那么就可以判断,多线程运行的代码在run方法中。然后我们不能把整个run方法都写入同步代码块中,那样岂不是成了单线程,所以要判断哪些是共享数据,一般来说,成员变量都是共享数据,只要是run方法中用到的成员变量,那么这些变量就是共享数据,但是共享数据如果只有一句的话,比如成员变量x,打印语句System.out.println(x++),这样一句语句,里面有共享数据,当多个线程执行到这部分时,不管哪个线程或停或执行,一句话过后,x都会改变,不会有x在两个线程的值是一样的。所哟要看多语句,比如:

                     void add(int x)   {

                                                        sum= sum+x;

                       System.out.println(sum);

                    }

当有这样同样的sum共享数据的时候,线程A在打印语句之前休眠,之后线程B进来再执行求和语句,那么sum此时就变了,线程A在执行是就会打印后面的结果,而不是线程A本身执行完的结果。所以对于多线的判断总结一下:

 

对于多线程安全问题的判断:

1、 明确哪些代码是多线程运行代码(一般是run方法中的代码)

2、 明确共享数据(一般是用到的成员变量)

3、 明确多线程运行代码中哪些语句是操作共享数据的(注意同一数据,大于两条语句的)。

 

通过以上的判断,我们就可以再相应的语句上加上同步代码块,这样坐到精准和细致。

Synchronized也可以直接加上某个函数上,形式为:

              public synchronized void add(intx){ }

这样同步代码就有两种形式:

一、       同步代码块

二、       同步函数

 

同步代码块有锁,同步函数也有锁。因为函数需要被对象调用,那么函数都有一个所属对象引用,就是this,所以同步函数使用的锁是this。如果同步函数被静态修饰的话,就为静态同步函数,而静态同步函数的锁是Class对象,比如:

            class  Demo implements Runnable{

                                     public static synchronized void add(int x){ }

}

看上述程序,当静态进内存的时候,内存中没有本类的对象,但是一定有该类对应的字节码文件对象,就是类名.class  对象的类型就是Class 。使用的锁就是该方法所在的字节码文件对象。则,此时的锁即是Demo.class

 

同步可以再单例设计模式中的懒汉式中可以用到,详情再查看设计模式之单例设计模式。

 

三、同步小点:死锁

死锁,就是A有一个锁,B有一个锁,A那这自己的锁想进B里面,B也拿着自己的锁,想进A里面,那么谁都不放锁,那么就会死锁。

一般程序里情况是:同步里嵌套同步。

我们要避免这中情况发生。

 

 

 

四、线程间通讯

线程间通讯就是多个线程在操作同一个资源,但是操作的动作不同。

看一个示例代码:

class Res {

数据变量;

}

class Input implements Runnable{

         public void run(){

         操作Res中的内容:给Res中输入数据。

         }

}

class Output implements Runnable{

         public void run(){

         操作Res中的内容:读取Res中的数据

         }

}

classTestForYou{

         public static void main(String[] args){

                   主函数中建立输入和输出线程。

         }

}

看上面的程序,应该明白什么事线程间通讯,就是操作同一数据,确实不同动作。当然,数据的输入和数据的输出,也得达到我们想要的效果。当然,会出现线程安全问题,按照多线程安全问题判断和同步前提两个规则来解决即可。

 

等待唤醒机制

wait():等待   锁.wait()

notify():唤醒  锁.notify()

notifyAll():全部唤醒

它们都是使用在同步中,因为要对持有监视器(锁)的线程操作。所以,都要使用在同步中,因为同步才具有监视器(锁)。

为什么这些方法定义在Object类中?因为这些方法在操作同步线程时,都必须要表示它们锁操作线程持有的锁,只有统一锁上的被等待线程,可以被同一个锁上的notify唤醒。也就是说等待和唤醒必须是同一个锁。而锁可以是任意对象,所以只能定义在Obiect类中。

 

情况一:之前,我们操作共享的数据的是两个线程,一个线程对共享数据的操作动作是输入,一个线程对共享数据的操作动作是输出,当只有两个线程的时候,我们是可以进行普通的方法进行同步,使得不会出现线程安全问题。

我们想输入一组数据后,在去除一组数据,这时就需要某个线程执行完,等待一段时间,这里就用到三个个,一是设定一个标记,二是用到wait(),三是notify()。比如下面这段程序中的一部分:

                            while(true){

                            synchronized(r){

                            if(r.flag)

                                     try{r.wait();}catch(Exceptione){}

                            if(x==0){

                            r.name ="lili";

                            r.sex ="woman";

                            }

                            else{

                            r.name ="wang  wu ";

                            r.sex ="  xxxx MAN";

                            }

                                     x=(x+1)%2;

                                     r.flag = true;

                                     r.notify();

                            }

                      }

r为共享数据的对象,name和sex为共享数据中的成员变量。

把flag标记初始化为false,在同步代码块中进行判断。走一遍顺序,if(r.flag)为假,那么就执行下面的输入数据的语句(x初始化为0),到后面改变flag的值为true,然后唤醒另一输入语句中的等待的线程,这时在回去判断flag的值为真,那么此线程就会等待,另一输出线程就会执行。看输出部分代码:

                   while(true){

                            synchronized(r){

                            if(!(r.flag))

                                     try{r.wait();}catch(Exceptione){}

                   System.out.println(r.name+".."+r.sex);

                   r.flag = false;

                   r.notify();

                            }

                   }

需要理解的是,线程等待是在一个线程池中,当notify要唤醒线程时,是要唤醒最早的那个等待的线程,这是默认方法。我们可以通过唤醒和锁有关的线程,来唤醒我们想要唤醒的行程,那么看上面程序,同步代码块的锁是共享数据对象r,所以,wait()和notify()前面加上锁,就相当于打上了标记,这样当程序运行时候,就会唤醒同一个锁的等待线程。

 

情况二:情况一是两个线程共享一个数据,如果多个线程共享一个数据呢?还是上面示例程序,我们建立两个输入数据线程和两个输出数据线程,按照程序执行顺序来说,某个时刻上,输入数据的连个线程,后一个线程可能会覆盖前一个线程的数据,意思就是说,当我们生产了两双鞋,但商家只卖出一双,或者是生产了一双鞋,商家卖出两双,这样显然是不合理的。我们可以再判断上做改动,使得每个线程被唤醒时,可以再次判断标记flag,把if判断改为while循环:whle(flag)。这样线程被唤醒时,就可以多次判断,不会出现上述情况。但另一个问题就产生了,因为执行权是随机的,那么这个修改的程序,所有线程有可能就会全部等待,这时,我们就用到另一关键字,notifyAll,就是唤醒当前所有线线程,这就避免了线程全部等待。

 

 

JDK1.5新特性:多线程新解决方案:Lock、Condition

JDK1.5中,有一个接口Lock,这个替代了synchronized,同时Lock使用到了一个Condition接口,这个接口替代了Object中的wait(),notify(),notifyAll()。

Lock中有lock和unlock方法,就是一个拿锁,一个放锁。

Condition中提供了await(),就相当于wait()。还提供了signal和signalAll方法,就相当于notify和notifyAll。具体实现方式看如下程序:

                   private  Lock  lock= new ReentrantLock();

                   private  Condition  condition = lock.newCondition();

………………………….省略部分代码

         publicvoid run()  throwsInterruptedExceprion  {

                   while(true){

                   lock.lock();

                   try{           

                            while(!(r.flag))

                                     condition.await();

                            System.out.println(r.name+".."+r.sex);

                            r.flag= false;

                            condition.signal();                   

                   }

                   finally{

                            lock.unlock();

                   }

有上述程序可知,我们创建一个Lock接口的子类对象,使用lock方法中的newCondition()来创建一个Condition的引用对象,这样其实就是持有lock锁的一个对象,而这个对象里面有await() , singal() ,signalAll(),方法。在执行程序部分,lock.lock()方法来持有一个锁,在判断标记后面,用condition.await()是当前线程等待(这里会有InterruptedException抛出,所以要用try加测,但不处理,我们也抛出异常),然后用condition.signal();   等待的线程,把lock.unlock()放到finally块中,是使解锁动作一定要执行。这就是程序中Lock类体系替代原有同步代码块的方式。其实,在这一部上也就是把同步代码块替换成了我们JDK1.5的新技术,运行起来还是会有问题。因为,condition.signal()唤醒的也是最先等待的线程,即是是换成condition.signalAll()唤醒全部等待线程,但是以前的那个线程全部等待的情况依旧会发生。这里,condition就发挥作用了。看下面程序:

             private Lock  lock= new ReentrantLock();

                   private  Condition  condition_in = lock.newCondition();

private  Condition  condition_out = lock.newCondition();

………………………….省略部分代码

         publicvoid run()  throwsInterruptedExceprion  {

                   while(true){

                   lock.lock();

                   try{           

                            while(!(r.flag))

                                     condition_in.await();

                            System.out.println(r.name+".."+r.sex);

                            r.flag= false;

                            condition_out.signal();                   

                   }

                   finally{

                            lock.unlock();

                   }

我们建立了两个Condition的对象,一个是为输入数据的,一个是为输出数据的,因为同样从Lock中建立的,所以持有同样的锁。当我们执行程序时,condition_in就会是当前线程等待,就是是此时输入线程等待,而输出方(程序格式和输入方相反),有一个condition_out会使输出方线程等待。与之前的一个Condition对象不同的是,当执行到唤醒操作的时候,输入方程序为:condition_out.signal(),这时只会唤醒condition_out对象相关的等待线程,就是说,两个Condition对象,持有同一个锁,但相当于分别给输入和输出方做了标记,值等待或只唤醒固定对象所对应的线程。

 

 

 

停止线程

我们如果需要停止线程,如何动作。

以前的代码是使用stop方法,但是这个方法已经过时了。

 

只有一种,run方法结束。因为我们建立线程的时候,就是调用的run方法,而run方法中运行的代码通常是循环结构,只要控制住循环,就可以让run方法结束,就是结束了线程。

所以1、定义循环结束标记,2、使用interrupt(中断)方法。注意点是,interrupt方法是使线程结束冻结状态,回到运行状态中来。程序如下:

         privateboolean flag = true;

                  public void run() {

                   while(flag){

                            System.out.println("luanqi ba zao");

                            }

         }

         publicvoid setFlag() {

                   flag = false;

         }

在一个方法中,或是其他方法,把循环标记改变即可,是循环结束,那么线程就结束了。

但是要注意个特殊的情况:

         privateboolean flag = true;

         publicvoid run(){

                   while(flag){

                            try

                            {

                                     wait();

                            }

                            catch(InterruptedException e)

                            {

                                     System.out.println(".....Wait..A.....");

                            }

                            System.out.println("................");

                            }

         }

         publicvoid setFlag(){

                   flag = false;

         }

 

注意这个情况,当两个线程执行时,可能两个线程都在wait出等待了,此时,即便是我们改变了标记flag的值,线程也不会结束。就是说:当线程处于冻结状态,就不会读取标记,那么线程就不会结束。

这里我们就需要用到Thread中的interrupt方法,这个方法就是强制使线程接触冻结状态,但不是使线程停止,而是使线程回复运行状态。

         在主函数中调用interrupt方法,使冻结的线程回到运行状态,既然回到运行状态,那么就好解决线程停止问题了。因为interrupt会抛出一个interruptException异常,所以有两个方法可以解决。一是在主函数中,在使用interrupt方法之前改变标记。二是在异常处理中,改变标记,因为既然抛出异常了,就说明我们强制中断冻结状态想要使线程停止,那么就在catch语句中改变标记即可。

 

 

 

多线程中一些其他方法

1、  setDaemon守护线程

守护线程就相当于后台线程,我们写的线程都是前台线程,这个方法就是当前台线程结束的时候,守护线程就会自动结束。拿毕老师的话来说,就是雅典娜over了,那圣斗士就都失业解散了。

注意的是使用方法:在建立线程之前设定。使用方法如下。

t1.setDaemon(true);

t1.start();

2、  Join方法

等待该线程终止(会抛出一个异常)。

那个例子来理解:

t1.start();

t1.join();

t2.start();

上例,当执行到join方法时,主线程就把执行权给到t1线程了,直到t1线程执行完毕,主线程才会获得执行权,继续下面开启线程的方法。如果这这种情况:

t1.start();

t2.start();

t1.join();

先建立了两个线程,当执行到join方法时,主线程就会交出执行权,此时,有两个线程t1和t2都可以执行,所以两个线程会交替执行。直到当t1线程执行完毕后,主线程才会获得到执行权。

简单来说:当A线程执行到了B线程的join()方法时,A就会等待,等待B线程都执行完,A才会执行。

Join可以用来临时加入线程执行。

 

 

3、  优先级和yield方法

1)优先级

线程组概念,就是A个线程开启了多个线程,那么这多个线程就属于A这个线程组。

通过Thread类中的toString方法,我们可以查看每个线程的优先级,即线程组。对于优先级,一共10级,默认是5级,就是说,你级数越高,CPU执行你的概率越高,当然仅是概率。我们可以用setPriority(int 级数)方法继续设置。

         2)yield方法

暂停当前正在执行的线程对象,并执行其他线程。方法时静态的。

就是暂停一下,这样使得其他线程有机会执行。

 

 

 

总结:

1)  对于线程安全问题,第一个解决方案是synchronized同步代码块,对线程运行代码中操作共同数据的语句进行同步,提高线程安全性。要注意的是,同步代码块的监视器即锁,是任意对象。

2)  同步代码块注意事项:一是有两个前提,1、多个线程,2、同一个锁。这样一定要注意,当线程出错时,一定是这两点。

3)  对什么地方加同步代码块的判断:1、明确哪些代码是多线程运行代码,2、明确哪些是共享数据,3、明确多线程运行代码中哪些语句是操作共享数据的。

4)  同步函数的锁是this,静态同步函数的锁是所属类的字节码,即Class

5)  同步中嵌套同步会形成死锁,要避免这样的编写。

6)  线程通信中(同步代码块方法),注意只有两个线程共享数据和多个线程共享数据时的区别。只有两个线程时,if判断标记即可,notify唤醒之前冻结的线程;多个线程,while循环判断标记,notify全部唤醒。

7)  线程通信中(Lock方法),用Lock方法注意的是,多个线程要建立多个Condition对象,以用于唤醒除本方线程的其他线程。其中await,signal都是Condition对象里的方法,用Condition兑现调用。开头的lock.lock(),在最后一定要解锁unlock,因为等待会有异常,所以要try-finally,在finally中解锁。

8)  停止线程中注意特殊情况,多个线程等待,循环不会结束,就是读不到结束标记。我们可以用interrupt方法中断冻结状态的线程,在其在判断标记钱或是异常处理中(interrupt会报出异常)改变标记,结束循环即可。

9)  守护线程用于建立线程钱,会在前台线程终止后立即终止。Join方法当A线程执行到了B线程的join()方法时,A就会等待,等待B线程都执行完,A才会执行。优先级有10级,用setPriority(int 级数)来设定,但只是CPU执行可能性提高。Yield方法时暂停一下线程,会释放执行权,减缓线程执行频率,临时释放,主要作用其实就是可以让其他线程有机会执行,有平均运行的效果。

10)             开发时怎么写线程,注意下面代码:

classDemo

{

public static void main(String[] args)

{

           循环代码1;

 

           循环代码2;

}

}

两个循环代码,可能是有很大数的循环,但是当单线程运行时候,尤其是循环代码1里面数字特别大,那么循环代码2就可能执行不到,那么我们这时间就可以用多线程。简单来说,就是某些代码要同时运行时,就用多线程代码进行封装。看程序:

classDemo {

public static void main(String[] args)      {

           new Thread(){

                    public void run(){

                             循环代码1

                    }

           }.start();

           Runnable r = new Runnable(){

                   pubilicvoid run(){

                             循环代码2;                   

                    }

           }

           Thread t = new Thread(r);

           r.start();

}

}

从业务角色到工作台:一步步创建 SAP Fiori Launchpad Space 与 Page SAP S/4HANA Launchpad 配置优化指南:从业务角色出发构建高效工作台 本文针对S/4HANA项目中用户普遍反映的"入口难找"问题,提出基于Spaces和Pages的系统化解决方案。通过"以工作岗位为中心"的设计理念,将Launchpad信息架构重构为:一个业务角色对应一个Space,每个Space包含1-5个Page,Page内按任务划分2-5个Section,每个Section放置3-7个Tiles。文章详细阐述了从Business Role入手配 阅读详情

相关推荐

LangChain与SkillLite集成:AI Agent安全沙箱实践

在AI与自动化技术领域,安全沙箱是实现可信计算的核心机制。其原理是通过资源隔离与权限控制,构建受限的执行环境。技术价值在于平衡功能开放性与系统安全性,尤其适用于处理用户提交的非受信代码或敏感数据。典型应用场景包括AI插件系统、在线代码评测平台等。本文以LangChain框架与SkillLite沙箱的深度集成为例,详解如何通过命名空间隔离、cgroups限制等机制,为AI Agent赋予安全执行动态技能的能力。其中涉及的关键技术点包括Python运行时隔离、动态资源配额管理,以及如何防范Shell注入等常见攻

weixin_34189116的博客 405

多线程二之线程安全与通信

一、简介 当多个线程同时访问共享数据时可能会出现问题,称为线程安全问题。 当多线程访问共享数据时,由于CPU的切换,导致一个线程只执行了关键代码的一部分,还没执行完 ,此时另一个线程参与进来,会导致共享的数据发生异常。 二、线程的同步机制synchronized + 锁 2.1 简介 同步:排队执行 , 效率低但是安全。 异步:同时执行 , 效率高但是数据不安全。 锁,也称为对象锁,每个对象都自带一个锁(标识),且不同对象的锁是不一样的 。 2.2 同步代码块和同步方法 2.2.1 同步的前提 必须有两

lykilxz的博客 204

基于车牌识别的停车收费系统的设计与实现(源码+开题)

本系统(程序源码)带文档lw万字以上文末可获取一份本项目的java源码和数据库参考。系统程序文件列表开题报告内容研究背景: 随着城市化进程的加速和汽车保有量的增加,停车难成为了一个普遍存在的问题。传统的停车收费方式存在着效率低下、管理混乱等问题。因此,开发一款基于车牌识别的停车收费系统具有重要的现实意义。研究意义: 基于车牌识别的停车收费系统可以有效地解决传统停车收费方式在效率和准确性方面的问题,提高停车服务的效率和质量。

迟限程序设计 1392

变量线程安全分析

一、成员变量和静态变量是否线程安全? 一、如果他们没有共享,则线程安全。 二、如果他们被共享了,根据他们的状态是否能够改变分为两种: 1、如果只读,则线程安全。 2、如果有读写操作,则这段代码时临界区,需要考虑线程安全 二、局部变量是否线程安全? 一、局部变量是线程安全的 public static void test1() { int i = 10; i++;//成员变量进行++操作时才会有多个步骤,而局部变量没有,他是原子性的 } 每个线程调用 test1() 方法时局部变量 i

weixin_42972832的博客 1023

Emuelec系统安装全流程:超详细版指南(从零开始)

手把手带你完成emuelec系统的完整安装,从基础准备到系统配置一步不落,适合新手入门。深入解析emuelec在各类设备上的部署技巧,让复古游戏体验更流畅。

weixin_42594419的博客 1972

HyperMesh二次开发实战:自动化Comp与材料属性批量绑定

本文详细介绍了HyperMesh二次开发中自动化Comp与材料属性批量绑定的实战技巧。通过TCL脚本实现批量创建属性卡、智能材料分配和异常处理,大幅提升前处理效率,适用于汽车、航空航天等领域的复杂模型处理。

weixin_29214691的博客 691

变量的线程安全分析

成员变量和静态变量是否线程安全? 如果它们没有共享,则线程安全。 如果它们被共享了,根据他们的状态是否能够改变,又分两种情况 只是读操作,则线程安全 如果有读写操作,则这段代码是临界区,需要考虑线程安全 局部变量是否线程安全? 局部变量是线程安全的 但局部变量引用的对象则未必 如果该对象没有逃离方法的作用范围,它是线程安全的 如果该对象逃离方法的作用范围,需要考虑线程安全 局部变量线程安全分析 想一想,这段代码被多个线程访问,它是线程安全的吗? public stati

Clawww的学习笔记 3684

MuJoCo 机械臂关节空间阻抗控制Impedance实现(附代码)

阻抗控制通过调整关节的刚度和阻尼,让机器人在接触时产生顺应性,减少冲击力,其核心目标是在接触外部载荷时能够自适应调整输出力矩,实现力与位置的协同控制。阻抗控制可以很快的到达设定位置,在此基础上,使用mujoco交互中的施加外力操作,可以看到当外力松开后,机械臂也可以很快的回弹回设定位置。其中self.Kp和self.Kd为固定刚度和阻尼系数,通过修改刚度和阻尼参数,可以变得更柔顺来应对各种场景。注释掉该行后,直接simulate仿真可以看到机械臂控制位置震荡等情况,接下来引入关节空间阻抗控制的代码。

darcsdn 1274

黑马程序员_2014 7月份 我对使用多线程的心得

2014 7月份 我对使用多线程的心得   本博客的题目就有些怪——2014 7月份 我对使用多线程的心得。加上日期,是因为我觉得,在学习编程这种纯思想上的技能。(有些技能是训练肌肉记忆,我觉得编程是与之相对的技能)。对编程语言的理解与使用,如果不断地认真学习,理解也会在不断地变化,提高。不同时期会有不同的认识,并且这种改变会很快。经常有时候看也前自己的学习笔记会发现自己很浅薄。但这些浅薄也正

javamu的专栏 926

内网环境下的高德地图离线化实战:从瓦片下载到交互功能集成

本文详细介绍了在内网环境中部署离线高德地图的完整实战方案。针对军工、能源、金融等对网络隔离与数据安全有严格要求的场景,文章核心解决了离线地图的两大基石:地图瓦片数据的高效下载与本地化,以及高德地图JS API的获取与插件集成。通过具体代码示例,进一步讲解了如何实现地图初始化、海量点标注与聚合、自定义图标及框选查询等核心交互功能,并分享了内网部署的路径配置、性能优化及法律合规等关键注意事项,为开发者在封闭网络环境下构建稳定、可控的地图应用提供了清晰指南。

Apple的专栏 395

基于STM32L4XX、HAL库的ICP-10111压力传感器驱动程序设计

define ICP10111_CMD_MEAS_ULN 0x7866 // 超低噪声模式。#define ICP10111_CMD_MEAS_LP 0x609C // 低功耗模式。#define ICP10111_CMD_MEAS_LN 0x70DF // 低噪声模式。#define ICP10111_CMD_MEAS_N 0x6825 // 正常模式。ICP10111_MODE_LN, // 低噪声。// 等待测量完成(根据模式不同等待时间不同)

zhusl6688的博客 417

黑马程序员-多线程

——- android培训、java培训、期待与您交流! ———-1.1 进程和线程进程:正在进行中的程序(直译)。 线程:进程中一个负责程序执行的控制单元(执行路径)。 一个进程中可以有多个执行路径,称之为多线程。 一个进程中至少要有一个线程。 开启多个线程是为了同时运行多部分代码,每一个线程都有自己运行的内容P.S.一个进程中有多个线程,称为多线程。 思考:jvm启动是单线程还是多线

sa_leon的博客 496

信奥赛C++提高组csp-s之数论基础专题课:从同余到分数模运算1(知识地图:同余、裴蜀定理、扩展欧几里得、乘法逆元、分数模运算)

信奥赛C++提高组csp-s之数论基础专题课:从同余到分数模运算1(知识地图:同余、裴蜀定理、扩展欧几里得、乘法逆元、分数模运算)

王老师青少年编程 791

多线程(黑马程序员)

newCachedThreadPool():线程数量随任务增加而增加,只想完毕60s挂掉。newFixedThreadPool(int ):创建固定数量线程池(挂了补充)newSingleThreadExecutor:创建单个线程线程池(挂了补充)参数六:threadFactory:指定线程池的线程工厂(创建线程)参数七:handler:指定线程池的任务拒绝策略(都满了怎么处理)参数二:maximumPoolSize:指定线程池最大线程数量。参数四:unit:临时线程存活时间单位(秒,分,时,天)

weixin_74390886的博客 1430

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

黑马程序员——多线程

——- android培训、java培训、期待与您交流! ———-黑马程序员多线程 创建线程方式一 线程的四种状态 创建线程方式二 线程安全问题 同步synchronized 线程间通信 停止线程 经典案例生产者消费者黑马程序员——多线程创建线程方式一 继承Thread类 子类覆盖父类中的run方法,将线程运行的代码存放在run中。 建立子类对象的同时线程也被创建。 通过调用start方法开启线程

jmw__的专栏 360

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

黑马程序员-【多线程】

一、什么是多线程 进程:是一个正在执行中的程序。每一个进程执行都有一个执行顺序。该顺序是一个执行路径,或者叫一个控制单元。 线程:是一组指令的集合,或者是程序的特殊段,它可以在程序里独立执行。也可以把它理解为代码运行的上下文。所以线程基本上是轻量级的进程,它负责在单个程序里执行多任务。通常由操作系统负责多个线程的调度和执行。     多线程是这样一种机制,它允许在程序中并发执行多个指令流,每

Hello World 924

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

黑马程序员——多线程(下)

——Java培训、Android培训、iOS培训、.Net培训、期待与您交流! ——-5.单例设计模式的安全问题请写一个延迟加载的单例模式?写懒汉式;当出现多线程访问时怎么解决?加同步,解决安全问题;效率高吗?不高;怎样解决?通过双重判断的形式解决。 //懒汉式:延迟加载方式。 当多线程访问懒汉式时,因为懒汉式的方法内对共性数据进行多条语句的操作。所以容易出现线程安全问题。为了解决,加入同步机制

a770772412的博客 273

黑马程序员——Java多线程

------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! ------- 自学Java第六天笔记。本人是根据毕向东老师的JavaSE视频学习的。 Java多线程 一.多线程理解。 1.进程: 是一个正在执行中的程序(其实进程就是一个应用程序运行时的内存分配空间)。每一个进程执行都有一个执行顺序。该顺序是一个执行路径,或者叫一个

zhaofengshiwo的专栏 428

黑马程序员_多线程技术

名词解析: 进程:一个程序在内存中的所处空间。进程只分配应用程序的内存空间,并不执行应用程序。 线程:就是进程中一个负责程序执行中的控制单元(执行路径) 垃圾回收器:垃圾回收线程 当垃圾回收时会执行object的finalize方法,我们可以用system.gc()来通知垃圾回收线程要开始回收垃圾了。 并发:就是”同时”的意思 CPU执行资格:当某线程start()开启之后就有了CPU

yanghu612的专栏 704

黑马程序员 多线程总结2

------- android培训、java培训、期待与您交流! -------------------------------- ASP.Net+Unity开发、.Net培训、期待与您交流! ---------------------- 详细请查看:www.itheima.com

gexiaodong1129的专栏 487

黑马程序员—多线程

------- android培训、java培训、期待与您交流! ---------- 进程:是一个正在执行中的程序。每一个进程执行都有一个执行顺序。该顺序是一个执行路径,或者叫一个控制单元。 线程:就是进程中的一个独立的控制单元。线程在控制着进程的执行。 一个进程中至少有一个线程。 Java VM  启动的时候会有一个进程java.exe. 该进程中至少一个线程负责java程序的执

continuenext的专栏 718

黑马程序员_多线程和String类

------------- android培训、java培训、java博客、java学习型技术博客、期待与您交流! ------------- 多线程 进程与线程 进程是程序的一次动态执行过程,它经历了代码加载、执行到执行完毕整个过程, 运行一个程序,就会启动一个进程,这时操作系统会为进程分配资源,最主要资源即内存空间; 多进程操作系统指能同时运行多个进程(

Afree_Yan 816

黑马程序员_java之多线程

------- android培训、java培训、期待与您交流! ----------   多线程:  1、多线程        进程:正在运行的程序叫进程        线程:进程在执行过程中,可能需要多个任务同时执行,每个任务的执行者就是线程  2、jvm启动是多线程  3、如何实现多线程:       A:继承Thread类      步骤:      定义一个类

wsw6807的专栏 303

黑马程序员_Java多线程

-------    android培训、java培训、期待与您交流! ----------

bearzw的博客 757

黑马程序员--多线程

——Java培训、Android培训、iOS培训、.Net培训、期待与您交流! ——- 注:视频来源,毕向东老师的 JAVA 基础视频。一、线程和进程1)进程:是一个在执行中的程序。每一个进程都有一个执行顺序,该顺序是一个执行路径,或者叫一个控制单元。2)线程:就是进程中的一个独立的控制单元。线程在控制着进程的执行。3) 理解:一个进程中,至少有一个线程。在JVM 启动的时候会有一个进程叫java

sinat_29779023的博客 973
上一篇: 黑马程序员_多线程(概念和创建)
下一篇: 黑马程序员_集合概述(Collection List&Set)
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值