Java多线程基础知识回顾与总结

【计算机组成原理】总线(一)—— 总线的概述与结构 总线是一组能为多个部件分时共享的公共信息传送线路。每个总线可能由很多根信号线组成。 阅读详情

1. 单核CPU和多核CPU与多线程的关系

1.1 如何查看自己PC的CPU是几核的:

(1):启动任务管理器 ==》点性能选项卡,可以看到CPU使用记录,下面有几个框就代表有几个核心。如下双核和四核的示例:
这里写图片描述

这里写图片描述

(2): 从设备管理器中查看,

这里写图片描述

(3):更多的查看方式,读者可以参考: 如何查看自己笔记本的CPU是几核

1.2 为什么多核处理器逐渐替代了单核处理器

在说这个问题时候 我们结合处理器的发展历程进行简单的说明:
==》 1971年,英特尔推出的全球第一颗通用型微处理器4004,由2300个晶体管构成。在一块芯片上集成的晶体管数目越多,意味着运算速度即主频就更快。今天英特尔的奔腾(Pentium)四至尊版840处理器,晶体管数量已经增加至2.5亿个,相比当年的4004增加了10万倍。其主频也从最初的740kHz(每秒钟可进行74万次运算),增长到现在的3.9GHz(每秒钟运算39亿次)以上。
==》但到了2005年,当主频接近4GHz时,英特尔和AMD发现,速度也会遇到自己的极限:那就是单纯的主频提升,已经无法明显提升系统整体性能,
因为:(1) 以英特尔发布的采用NetBurst架构的奔腾四CPU为例,Netburst微架构的好处在于方便提升频率,可以让产品的主频非常高。但性能提升并不明显,频率提高50%,性能提升可能微不足道。由于流水线过长,使得单位频率效能低下,加上由于缓存的增加和漏电流控制不利造成功耗大幅度增加,3.6GHz奔腾四芯片在性能上反而还不如早些时推出的3.4GHz产品。所以,Prescott产品系列只达到3.8G,就戛然而止。
(2)随着功率增大,散热问题也越来越成为一个无法逾越的障碍。据测算,主频每增加1G,功耗将上升25瓦,而在芯片功耗超过150瓦后,现有的风冷散热系统将无法满足散热的需要。
==》 因此 在“纵向扩充”得不到满足时,人民自然想到了“横向扩充”,这样多核的时代就悄然而至,但真正的“双核元年”,则被认为是2006年。这一年的7月23日,英特尔基于酷睿(Core)架构的处理器正式发布。
多核处理器 指在一枚处理器中集成两个或多个完整的计算引擎(内核),此时处理器能支持系统总线上的多个处理器,由总线控制器提供所有总线控制信号和命令信号。
多核处理器是单枚芯片(也称为“硅核”),能够直接插入单一的处理器插槽中,但操作系统会利用所有相关的资源,将每个执行内核作为分立的逻辑处理器。通过在两个执行内核之间划分任务,多核处理器可在特定的时钟周期内执行更多任务。

1.3 多核处理器的优势
  • 对于多线程开发的程序而言:
    程序采用了线程级并行编程,那么这个程序在运行时可以把并行的线程同时交付给两个核心分别处理,因而程序运行速度得到极大提高。对于这类程序,两个物理核心和两颗处理器基本上是等价的,所以,这些程序往往可以不作任何改动就直接运行在双核电脑上。

    例如:
    (1):打开IE浏览器上网。看似简单的一个操作,实际上浏览器进程会调用代码解析、Flash播放、多媒体播放、Java、脚本解析等一系列线程,这些线程可以并行地被双核处理器处理,因而运行速度大大加快。
    (2):对于这些单线程的程序例如一些文件压缩软件、部分游戏软件等等。单独运行在多核处理器上与单独运行在同样参数的单核处理器上没有明显的差别。但是,由于日常使用的最最基本的程序——操作系统——是支持并行处理的,所以,当在多核处理器上同时运行多个单线程程序的时候,操作系统会把多个程序的指令分别发送给多个核心,从而使得同时完成多个程序的速度大大加快。

1.4 技术关键
  1. 核结构研究: 同构 VS 异构
  2. 程序执行模型:程序执行模型是编译器设计人员与系统实现人员之间的接口,编译器设计人员决定如何将一种高级语言程序按一种程序执行模型转换成一种目标机器语言程序;
    系统实现人员则决定该程序执行模型在具体目标机器上的有效实现。
  3. Cache设计:处理器和主存间的速度差距对CMP来说是个突出的矛盾,因此必须使用多级Cache来缓解。
  4. 核间通信技术:目前比较主流的片上高效通信机制有两种,一种是基于总线共享的Cache结构,一种是基于片上的互连结构。
  5. 总线设计:当多个CPU核心同时要求访问内存或多个CPU核心内私有Cache同时出现Cache不命中事件时,BIU对这多个访问请求的仲裁机制以及对外存储访问的转换机制的效率决定了CMP系统的整体性能。
  6. 操作系统设计:任务调度、中断处理、同步互斥。

    在此声明: 上面关于多核处理器的介绍是总结和简化百度百科关于多核处理器的内容,原文写的相当不错,建议有耐心的同志们好好看看:多核处理器


2. Java线程的几种状态

2.1 sleep() join() yield() 和 wait() 的比较分析
  • sleep() 和 join() 类似,我们在此只对 sleep() 方法进行分析: sleep(time)停止当前线程,但是并不释放该线程所占有的资源,尤其是对锁标识的占有,也就是说当线程调用了sleep(time)后,线程进入阻塞状态,但是线程不会释放对锁标识的占有,当线程
    睡完后,如果获得cpu的执行权,则继续向下执行,即这个阻塞状态是:具有执行资格(没有释放资源),但没有cpu的执行权(让出了cpu的执行权)。

  • wait(): 线程进入阻塞状态进入等待池中等待,并且释放资源(也就是释放了对锁标识的占有),等待notify() 的唤醒,唤醒后线程进入锁标识池重新对锁标识进行竞争。由于wait() 和
    notify()是对锁的占有和释放,因此必须出现在sychronized中,

sychronized(Lock.class){//某一线程获得锁标识,
    Lock.class.wait(); //wait()是线程释放锁标识进入阻塞状态
}
Lock.class.notify(); //唤醒线程让线程重新去竞争锁标识

这里写图片描述

2.2 线程的五种状态,

参考了好多资料有说4中状态又说5种状态甚至8种状态,本人按自己的粗浅理解将线程归结为以下5种状态:

  • 创建状态 (New Thread)

在 Java 语言中使用 new操作符创建一个线程后,该线程仅仅是一个空对象,它具备了线程的一些特征,但此时系统没有为其分配资源,这时的线程处于创建状态。

  • 可运行状态 (Runnable)

使用 start()方法启动一个线程后,系统为该线程分配了除 CPU 外的所需资源,使该线程处于就绪状态。此外,如果某个线程执行了 yield() 方法,那么该线程会被暂时剥夺 CPU 资源,重新进入就绪状态。

  • 运行状态 (Running)

Java运行系统通过调度选中一个处于就绪状态的线程,使其占有 CPU 并转为运行状态。此时,系统真正执行线程的 run() 方法。

  • 阻塞状态 (Blocked)

一个正在运行的线程因某些原因不能继续运行时,它就进入阻塞状态。
这些原因包括:
当执行了某个线程对象sleep()等阻塞类型的方法时,该线程对象会被置入一个阻塞集(Blocked Pool)内,超时而时自动苏醒;
当多个线程试图进入某个同步区域(synchronized)时,没能进入该同步区域的线程会被置入锁定集(Lock Pool),直到获得该同步区域的锁,进入就绪状态;
当线程执行了某个对象的 wait() 方法时,线程会被置入该对象的等待集(Wait Pool)中,直到执行了该对象的 notify()方法,wait()/notify()方法的执行要求线程首先获取到该对象的锁。

  • 死亡状态 (Dead)

线程在 run() 方法执行结束后进入死亡状态。此外,如果线程执行了 interrupt() 或 stop() 方法,那么它也会以异常退出的方式进入死亡状态。

这里写图片描述


3. 死锁原因即死锁示例:

锁:一种sychronized 一种Lock, 以sychronized为例,要想产生死锁,肯定是多个线程相互争抢对方所持有的锁,争抢僵持,导致死锁:

  • 线程ThreadA先获取锁ThreadA.classs,然后在同步块里嵌套竞争锁ThreadB.class。而线程ThreadB先获取锁ThreadB.class,然后在同步块里嵌套竞争锁ThreadA.class.

  • 此时锁ThreadA.classs已经被线程ThreadA拥有,而ThreadA在等待ThreadB.classs,而ThreadB.classs被ThreadB拥有,ThreadB在等待ThreadA.classs……无线循环)。

示例:

package dead.lock;

/*
 * 请写一个死锁实例:
 * 产生死锁的前提:
 * 多个线程操作,在sychronized中锁嵌套
 * 产生死锁的原因:
 * 两个或两个以上线程彼此等待拿到对方的锁,
 * */

class ThreadA extends Thread{

    ThreadA(String name){
        super(name);
    }

    @Override
    public void run() {
        while(true){    
            synchronized(ThreadA.class){
                System.out.println(Thread.currentThread().getName()+ " hava lock ThreadA.class");
                synchronized(ThreadB.class){
                    System.out.println(Thread.currentThread().getName()+" hava lock ThreadB.class");
                    System.out.println(Thread.currentThread().getName()+" free Lock A and B");
                }
            }
            System.out.println(Thread.currentThread().getName()+".....runing");
        }
    }

}

class ThreadB extends Thread{

    ThreadB(String name){
        super(name);
    }

    public void run() {
        while(true){    
            synchronized(ThreadB.class){
                System.out.println(Thread.currentThread().getName()+ " hava lock ThreadB.class");
                synchronized(ThreadA.class){
                    System.out.println(Thread.currentThread().getName()+" hava lock ThreadA.class");
                    System.out.println(Thread.currentThread().getName()+" free Lock B and A");
                }
            }
            System.out.println(Thread.currentThread().getName()+".....runing");
        }
    }

}

public class DeadLockDemo {

    public static void main(String[] args) {
        new ThreadA("Thread A-1 ").start();
        new ThreadA("Thread A-2 ").start();
        new ThreadB("Thread B-1 ").start();
        new ThreadB("Thread B-2 ").start();
    }

}

输出结果:

Thread A-1  hava lock ThreadA.class
Thread A-1  hava lock ThreadB.class
Thread A-1  free Lock A and B
Thread A-1 .....runing
Thread A-2  hava lock ThreadA.class
Thread A-2  hava lock ThreadB.class
Thread A-2  free Lock A and B
Thread A-2 .....runing
Thread A-2  hava lock ThreadA.class
Thread B-1  hava lock ThreadB.class

4. 生产者消费者示例分析: 死锁,代码优化

package dead.lock;

/**
 * 生产和消费公共操纵的资源,并且假设生产一个消费一个
 * @author Administrator
 *
 */
class Resource{
    private int count=1;
    private boolean flag = true;//用于判断仓库中是否有产品真:有空位

    public synchronized void pro(){
        //while(!flag)//与notifyAll对应
        if(!flag)

            try {
                this.wait();
            } catch (InterruptedException e) {
                System.out.println(Thread.currentThread().getName()+" pro Interrupted");
            }
        try {
            Thread.sleep(10);
            flag = false;
            System.out.println(Thread.currentThread().getName()+"生产了商品 .."+ count++);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        //唤醒消费者线程
        this.notify();//只是唤醒了最先等待的线程,不一定能唤醒对方;
        //this.notifyAll();//只是唤醒了所有等待的线程
    }

    public synchronized void cus(){
        //while(flag)//与notifyAll()对应
        if(flag)
            try {
                this.wait();
            } catch (InterruptedException e) {
                System.out.println(Thread.currentThread().getName()+" cus Interrupted");
            }
        try {
            Thread.sleep(5);
            flag = true;
            System.out.println(Thread.currentThread().getName()+"消费了商品 ...."+ (count-1));
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        //唤醒生产者线程进行生产
        this.notify();
        //this.notifyAll();
    }
}


public class ProAndCusDemo {

    public static void main(String[] args) {
        Resource r = new Resource();
        for(int i=0;i<3;i++){
            new Thread("proTh-"+i){
                public void run(){
                    while(true)
                        r.pro();
                }
            }.start();

            new Thread("cusTh-"+i){
                public void run(){
                    while(true)
                        r.cus();
                }
            }.start();
        }

    }

}

输出结果:

这里写图片描述

结果分析:

这里写图片描述


5. 通过Lock 和 Condition对上述代码 sychronized 和 wait notify进行改写;

5.1 Lock 替换 synchronized

在Java1.5以后 Lock 实现提供了比使用 synchronized 方法和语句可获得的更广泛的锁定操作。我们用Lock来代替了synchronized.

需要注意的是,用sychronized修饰的方法或者语句块在代码执行完之后锁自动释放,而是用Lock需要我们手动释放锁,所以为了保证锁最终被释放(发生异常情况),要把互斥区放在try内,释放锁放在finally内。
如下两种代码是等价的:

class LockDemo {    
    private Lock lock = new ReentrantLock();// 锁对象    

    public void method(int size) {           
        lock.lock();      // 得到锁      
        try {    
            for(int i = 0; i < size; i++) {    
                System.out.print("LockDemo method content!");    
            }    
        } finally {    
            lock.unlock();// 释放锁    
        }    
    }    
}    
class SynchronizedDemo {    
    public void method(int size) {           
      sychronized(SynchronizedDemo.class)  // 得到锁      
      {    
          for(int i = 0; i < size; i++) {    
              System.out.print("SynchronizedDemo method content!");    
          }
       } //执行完成自动释放锁。   
    }    
}    
5.2 Condition的await()替换wait(),用signal()替换notify(),用signalAll()替换notifyAll()。

Condition是被绑定到Lock上的,要创建一个Lock的Condition必须用newCondition()方法。

对上例 生产消费示例进行更改如下:

package dead.lock;

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

/**
 * 生产和消费公共操纵的资源,并且假设生产一个消费一个
 * @author Administrator
 *
 */
class Resource2{
    private int count=1;
    private boolean flag = true;//用于判断仓库中是否有产品真:有空位

    //增加的代码
    Lock lock = new ReentrantLock();
    Condition conPro = lock.newCondition(),
            conCus = lock.newCondition();

    public void pro(){
        lock.lock();//关键代码
        try {
            while (!flag)
                conPro.await();//关键代码1
            flag = false;
            Thread.sleep(10);
            System.out.println(Thread.currentThread().getName()+"生产了商品 .."+ count++);
            conCus.signal();//关键代码2
        } catch (InterruptedException e1) {
            System.out.println(Thread.currentThread().getName()+" pro Interrupted");
        } finally {
            lock.unlock();//关键代码
        }
    }

    public void cus(){
        lock.lock();//关键代码
        try{
            while(flag)
                conCus.await();//关键代码1
            flag = true;
            Thread.sleep(10);
            System.out.println(Thread.currentThread().getName()+"消费了商品 ...."+ (count-1));
            conPro.signal();//关键代码2
        } catch(InterruptedException e1){
            System.out.println(Thread.currentThread().getName()+" cus Interrupted");
        } finally{
            lock.unlock();//关键代码
        }
    }
}


public class ProAndCusDemo2 {

    public static void main(String[] args) {
        Resource2 r = new Resource2();
        for(int i=0;i<3;i++){
            new Thread("proTh-"+i){
                public void run(){
                    while(true)
                        r.pro();
                }
            }.start();

            new Thread("cusTh-"+i){
                public void run(){
                    while(true)
                        r.cus();
                }
            }.start();
        }
    }

}

并发编程系列之线程基础知识回顾 并发编程系列之线程基础知识回顾,并发多线程的知识是很重要而且比较杂的知识点,所以需要花不少时间用于整理。问题1、使用多线程的目的是什么?充分利用cpu资源,可以并发的处理任务 阅读详情

相关推荐

InternVL 3.5 深度解析:开源多模态模型的新里程碑

InternVL 3.5是由上海人工智能实验室OpenGVLab团队推出的开源多模态大模型,在推理能力、效率和灵活性方面取得突破。该模型采用ViT-MLP-LLM架构,包含60亿参数的InternViT-6B视觉编码器和多种规格的语言模型骨干。核心创新包括:1)Cascade RL强化学习框架,通过离线热身和在线强化两阶段训练提升推理能力;2)ViR视觉分辨率路由器,动态调整图像处理分辨率以优化计算效率;3)DvD动态视觉token压缩技术。模型系列涵盖2B到241B参数规模,满足从边缘设备到高性能计算的不

m0_47999117的博客 1027

java基础学习总结——面向对象1

目录 一、面向过程的思想和面向对象的思想 二、简单理解面向对象 三、面向对象的设计思想 四、对象和类的概念 五、如何抽象出一个类? 六、类(对象)之间的关系 七、Java与面向对象 八、为什么使用面向对象编程? 一、面向过程的思想和面向对象的思想 面向对象和面向过程的思想有着本质上的区别, 作为面向对象的思维来说,当你拿到一个问题时,你分析这个问题不再是...

weixin_30591551的博客 1463

Vivado时序约束实战:input_delay在高速接口设计中的关键作用

本文深入探讨了在Vivado时序约束中,input_delay对于高速接口设计的关键作用。通过一个RGMII以太网接口调试的实际案例,解释了为何仅靠仿真正确而实际数据采集会失败,并揭示了set_input_delay约束的本质是告知时序分析工具外部芯片的时序关系,而非添加物理延迟。文章详细讲解了如何根据数据手册计算约束值、针对不同采样时钟方案(如移相时钟)进行约束,并指导如何通过时序报告验证约束效果,是解决FPGA高速接口时序问题的实战指南。

ee345的博客 252

Java多线程基础知识回顾与总结;

进程:就是正在运行中的程序,他分为多个线程;是操作系统的概念; 线程:是一个控制单元,也叫一个执行单元,CPU在多个线程中做着快速的切换;是应用程序的概念; 那么为什么要有多线程呢?说实话这个我也不是很清楚,毕老师说是为了提高执行效率,张老师说多线程不能够提高执行效率; 也许是他们基于的知识点不通,目前还是先学会怎么用吧!   线程的五种状态:创建,临时状态(阻塞状态,具有执行资格,但是还没有cp

李荣强 428

电商客服效率翻倍!手把手教你用影刀RPA+AI搭建智能回复系统(附实战配置)

本文详细介绍了如何利用影刀RPA+AI技术搭建电商智能客服系统,实现24小时在线回复,大幅提升客服效率。通过零代码配置、Excel词库管理和AI语义理解,系统能处理80%常规咨询,响应速度稳定在3秒内,特别适合中小电商降低成本并提升服务质量。

weixin_42520661的博客 547

Vue3+codemirror6实现公式(规则)编辑器

vue3+codemirror6+ts实现公式编辑器,可以插入标签、公式,也有补全提示

小阮的笔记本 5043

Java IO : Socket及多线程基础知识回顾

URL格式: 域名的解析:从右向左解析 域名的层级: 网络编程的本质是进程间通信。 通信的基础是IO模型。 Socket也是一种数据源! Socket是网络通信的端点。 通过Socket发送数据: 通过Socket接收数据: 同步/异步/阻塞/非阻塞: 同步/异步: 关注点在接收方怎样处理。若等待接收方处理完成后返回称同步;接收方收到请求后立即返回给发送方,且接收方处理完成后再将结果通知发送方称为异步。 阻塞/非阻塞:关注点在发送方怎样处理。若发送请求的一方(发送者)等待请求

OneFine的技术博客 561

卡尔曼滤波算法-Kalman Filter Algorithm

Kalman滤波是一种递归过程,主要有两个更新过程:时间更新和观测更新,其中时间更新主要包括状态预测和协方差预测,主要是对系统的预测,而观测更新主要包括计算卡尔曼增益、状态更新和协方差更新,因此整个递归过程主要包括五个方面的计算:1)状态预测;2)协方差预测;3)卡尔曼增益;4)状态更新;5)协方差更新; 用数学公式表示,如下: 状态预测:(1) 其中,X(k|k)是k时...

sunlin972913894的博客 2万+

java 5 多线程_Java基础知识回顾之五 ----- 多线程

前言在上一篇文章中,回顾了Java的集合。而在本篇文章中主要介绍多线程的相关知识。主要介绍的知识点为线程的介绍、多线程的使用、以及在多线程中使用的一些方法。线程和进程线程表示进程中负责程序执行的执行单元,依靠程序进行运行。线程是程序中的顺序控制流,只能使用分配给程序的资源和环境。进程表示资源的分配和调度的一个独立单元,通常表示为执行中的程序。一个进程至少包含一个线程。进程和线程的区别进程至少有一个...

weixin_33592736的博客 165

Python数据爬取超详细讲解(零基础入门,老年人都看的懂)

Python数据爬取超详细讲解(零基础入门,老年人都看的懂)

python03011的博客 3751

34、实数域上高效负循环卷积算法解析

本文介绍了一种高效的实数域负循环卷积算法,通过引入离散傅里叶负循环变换(DFNT)避免传统方法的冗余,显著提升计算效率。文章详细分析了算法原理、误差传播机制,并推导出误差与方差界,提出无误差和基于3σ规则的参数设置方案。结合Cooley-Tukey与Gentleman-Sande FFT路径优化,实验验证了算法在不同精度和多项式长度下的性能优势与结果正确性,为密码学与信号处理等领域提供了高精度、高性能的卷积计算解决方案。

salt的博客 113

Java基础知识回顾之五 ----- 多线程

前言 在上一篇文章中,回顾了Java的集合。而在本篇文章中主要介绍多线程的相关知识。主要介绍的知识点为线程的介绍、多线程的使用、以及在多线程中使用的一些方法。 线程和进程 线程 表示进程中负责程序执行的执行单元,依靠程序进行运行。线程是程序中的顺序控制流,只能使用分配给程序的资源和环境。 进程 表示资源的分配和调度的一个独立单元,通常表示为执行中的程序。一个进程至少包含一个线程。 进程和线程的区别...

weixin_34249367的博客 236

基于 Vivado HLS 的 AC97 音频系统设计

介绍一种基于 FPGA 的 AC97 音频系统设计。系统的核心部件采用 Xilinx Atlys 的板载 Spartan6 XCSLX45 芯片,使用的工具为 Xilinx 的高层 次 综 合 技 术 Vivado HLS。首先使用 C /C + + 代码编写的算法描述系统的 FIR 滤波器; 然后按 照 Vivado HLS 编译工具的规范,将程序代码转换为 RTL 模型,快速、直接地生成对 应左右声道的 FIR IP 核和综合结果; 再结合互连的 MicroBlaze 处理器 IP 核,处理 一段立体声

qq_43416206的博客 325

Java基础知识回顾第九篇 - Java异常机制 | 认识多线程

1、Java异常机制(Exception和Error) 我们先通过下面的一张图看看java异常层次结构:  从图中可以看出,不管是Exception还是Error,它们都继承自Throwable。下面我们来分别认识一下Exception和Error。   总的来说的,Exception和Error是一种不正常的行为,或许是程序本身导致的,也或许是系统导致的。 Exception:可以...

flappy tortoise 186

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

Java多线程实战-实现多线程文件下载,支持断点续传、日志记录等功能

本文将介绍如何通过Java来实现一个多线程下载器。作者:牵着猫散步的鼠鼠

qq_35716689的博客 25万+

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

Java基础知识回顾

关于JavaSE的一些比较基础的内容回顾,也是开始准备秋招和实习了qwq

backordinary的博客 1112

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

JAVA基础知识回顾-----多线程基础-----随想随写

下载 经常会有人问你,什么是进程,什么是线程,进程和线程有什么关系 (区别),所以我觉得还是有必要总结一下的,虽然可能不太好; 1.定义:所谓进程,就是正在进行的程序,每一个进程都有自己独立的一块 内存空间,比如在Windows系统下,一个EXE就是一个进程,可以在任务管理下 查看你运行的所有进程,而针对于此,线程指的是进程中的一个执行流程, 一个进程可以包含多个线程,多个线程共享一片内

hangge110的博客 383

总结回顾Java基础知识:

static除了不能访问构造器,像内部类,代码快,方法,内部类,成员变量都可以修饰。static修饰的成员成为类成员,类成员属于整个类,不属于单个对象。规则:类成员不能访问实力成员,作用域,类成员作用于大于实例,随着整个类加载,很容易导致类成员加载完成,实例还未初始化引发大量错误。static修饰类叫静态内部类,只能存在于内部类,通过外部类名.调用,只能访问外部静态成员。一切接对象,不同于面向过程,将问题拆解成对象,通过对象交互关联完成任务,简单优雅,缩短项目开发时间,在此之上,有继承,多态,封装等特性。

panpanaa的博客 296

java基础知识回顾之java Thread类学习(六)--java多线程同步函数用的锁

1.验证同步函数使用的锁----普通方法使用的锁 思路:创建两个线程,同时操作同一个资源,还是用卖票的例子来验证。创建好两个线程t1,t2,t1线程走同步代码块操作tickets,t2,线程走同步函数封装的代码操作tickets,同步代码块中的锁我们可以指定。假设我们事先不知道同步函数用的是什么锁;如果在同步代码块中指定的某个锁(测试)和同步函数用的锁相同,就不会出现线程安全问题,如果锁不相...

weixin_33973600的博客 120

暂停多线程c++_Java多线程编程核心技术总结

最近在复习多线程,看到有网友推荐高洪岩的《Java多线程编程核心技术》,于是就去图书馆借来看看,以此回顾一下多线程编程的基础知识,在此做一下学习笔记。全书都是很基础的东西,总体来说还是不错的,唯一的缺点是有一些多线程问题没有讲清楚原理,只是用代码说明的,例如SimpleDateFormat非线程安全,但是没有讲明白为什么非线程安全。要是再加上几句话说明一下就好了,还有就是没有对线程池进行...

weixin_39926613的博客 98
上一篇: JAVA-JDBC: (4) DAO设计思想及骨架搭建
下一篇: 初识 Maven
Coder-Qian
博客等级 码龄11年 63粉丝 73原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值