首页 > 编程语言 >面经梳理-java多线程基础

面经梳理-java多线程基础

时间:2024-06-17 21:55:22浏览次数:29  
标签:11 java prio Thread 面经 base 线程 多线程

题目

线程和进程的概念?守护线程是干什么的?常见的守护线程有哪些?

线程和进程的概念

进程是程序的运行实例,是程序向操作系统申请资源的基本单位,线程是进程的一条执行路径。
Java的线程分为两种:用户线程和守护线程。守护线程作用是为其他线程提供服务,如果所有的用户线程死亡,后台线程都会死亡。

常见的守护线程有哪些

守护线程最典型代表就是GC线程。

参考:
Java 守护线程Daemon
《Java多线程编程实战指南》黄文海
《Java疯狂讲义》李刚

并发和并行的概念?Java实现并发的方式?

并发和并行的概念

从软件的角度来说,并发就是在一段时间内以交替的方式去完成多个任务,而并行就是以齐头并进的方式去完成多个任务。
从硬件的角度来说,在一个处理器一次只能够运行一个线程的情况下,由于处理器可以使用时间片(Time-slice)分配的技术来实现在同一段时间内运行多个线程,因此一个处理器就可以实现并发。而并行则需要靠多个处理器在同一时刻各自运行一个线程来实现。

Java实现并发的方式

  • 继承Thread类
//实现方法的类
public class Demo1 extends Thread {
    public void run(){
        System.out.println("继承Thread类");
    }
}

//执行的方法
public static void main(String[] args) {
        Demo1 demo1=new Demo1();
        demo1.start();
}

执行结果:
继承Thread类
  • 实现Runnable接口
//实现的方法类:
public class Demo2 implements Runnable {
    @Override
    public void run() {
        System.out.println("实现runnable接口");
    }

}

//执行方法:
public static void main(String[] args) {
        Demo2 demo2=new Demo2();
        Thread thread=new Thread(demo2);
        thread.start();
}
    
执行结果:
实现runnable接口
  • 通过实现Callable接口
//实现类方法:
public class Demo3 implements Callable {
    @Override
    public Object call() {
        return "1";
    }
}

//执行方法:
public static void main(String[] args) {
		//创建实现类对象
        Callable demo3=new Demo3();
        FutureTask oneTask = new FutureTask(demo3);
        Thread thread = new Thread(oneTask);
        thread.start();
        Object o = null;
        try {
        	//获取返回值
            o = oneTask.get();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
        System.out.println(o);

}

执行结果:
1
  • 通过线程池来实现多线程
//实现代码如下:
public class Demo5 {
    public static void main(String[] args) {
        ExecutorService executorService = Executors.newFixedThreadPool(5);
        for(int i=0;i<5;i++){
            int finalI = i;
            executorService.execute(()-> {
                System.out.println(finalI);
            });
        }
    }
}

执行结果:
2
3
4
1
0

参考:
《Java多线程编程实战指南》黄文海
浅谈实现并发的几种方式

native关键字的作用是什么?

  • 作用

使用native关键字说明这个方法是原生方法,也就是这个方法是用C/C++语言实现的,并且被编译成了DLL,由java去调用。
这些函数的实现体在DLL中,JDK的源代码中并不包含。对于不同的平台它们也是不同的。这也是java的底层机制,实际上java就是在不同的平台上调用不同的native方法实现对操作系统的访问的。

  • 使用

可以将native方法比作Java程序同C程序的接口,其实现步骤:
  1、在Java中声明native()方法,然后编译;
  2、用javac -h产生一个.h文件;
  3、写一个.cpp文件实现native导出方法,其中需要包含第二步产生的.h文件(注意其中又包含了JDK带的jni.h文件);
  4、将第三步的.cpp文件编译成动态链接库文件;
  5、在Java中用System.loadLibrary()方法加载第四步产生的动态链接库文件,这个native()方法就可以在Java中被访问了。

参考:
Java中Native关键字的作用

线程的状态有哪些,是怎么转换的?Jvm怎么查看线程的运行状态?

线程的状态有哪些,是怎么转换的

Java线程的状态可以使用监控工具查看,也可以通过Thread.getState()调用来获取。Thread.getState()的返回值类型Thread.State是一个枚举类型(Enum)。Thread.State所定义的线程状态包括以下几种。
NEW:一个已创建而未启动的线程处于该状态。由于一个线程实例只能够被启动一次,因此一个线程只可能有一次处于该状态。
RUNNABLE:该状态可以被看成一个复合状态。它包括两个子状态:READY和RUNNING。前者表示处于该状态的线程可以被线程调度器(Scheduler)进行调度而使之处于RUNNING状态。后者表示处于该状态的线程正在运行,即相应线程对象的run方法所对应的指令正在由处理器执行。执行Thread.yield()的线程,其状态可能会由RUNNING转换为READY。处于READY子状态的线程也被称为活跃线程。
BLOCKED:一个线程发起一个阻塞式I/O(BlockingI/O)操作后,或者申请一个由其他线程持有的独占资源(比如锁)时,相应的线程会处于该状态。处于BLOCKED状态的线程并不会占用处理器资源。当阻塞式I/O操作完成后,或者线程获得了其申请的资源,该线程的状态又可以转换为RUNNABLE。
WAITING:一个线程执行了某些特定方法之后就会处于这种等待其他线程执行另外一些特定操作的状态。能够使其执行线程变更为WAITING状态的方法包括:Object.wait()、Thread.join()和LockSupport.park(Object)。能够使相应线程从WAITING变更为RUNNABLE的相应方法包括:Object.notify()/notifyAll()和LockSupport.unpark(Object))。
TIMED_WAITING:该状态和WAITING类似,差别在于处于该状态的线程并非无限制地等待其他线程执行特定操作,而是处于带有时间限制的等待状态。当其他线程没有在指定时间内执行该线程所期望的特定操作时,该线程的状态自动转换为RUNNABLE。
TERMINATED:已经执行结束的线程处于该状态。由于一个线程实例只能够被启动一次,因此一个线程也只可能有一次处于该状态。Thread.run()正常返回或者由于抛出异常而提前终止都会导致相应线程处于该状态。一个线程在其整个生命周期中,只可能有一次处于NEW状态和TERMINATED状态。

Jvm怎么查看线程的运行状态

对线程进行监视的主要途径是获取并查看程序的线程转储(ThreadDump)。一个程序的线程转储包含了获取这个线程转储的那一刻该程序的线程信息。这些信息包括程序中有哪些线程以及这些线程的具体信息。常用线程转储的方法如下:

  • jstack

功能描述:
jstack用于生成java虚拟机当前时刻的线程快照。线程快照是当前java虚拟机内每一条线程正在执行的方法堆栈的集合,生成线程快照的主要目的是定位线程出现长时间停顿的原因,如线程间死锁、死循环、请求外部资源导致的长时间等待等。
命令用法:
jstack [ option ] vmid
主要选项:
-l 打印锁的额外信息
-e 打印线程的额外信息

举例:

C:\Users\liuwe>jstack -l 16788
2023-01-23 16:57:23
Full thread dump OpenJDK 64-Bit Server VM (11+28 mixed mode):

Threads class SMR info:
_java_thread_list=0x0000024591cff610, length=11, elements={
0x00000245f256d000, 0x00000245911b3000, 0x00000245911b4000, 0x0000024591a43000,
0x00000245911e9000, 0x00000245911eb800, 0x00000245911f2000, 0x0000024591ab0000,
0x00000245f264d000, 0x0000024591d54000, 0x0000024591d2d800
}

"main" #1 prio=5 os_prio=0 cpu=20078.13ms elapsed=28.27s tid=0x00000245f256d000 nid=0x3f48 runnable  [0x0000005b97bff000]
   java.lang.Thread.State: RUNNABLE
        at java.io.FileOutputStream.writeBytes(java.base@11/Native Method)
        at java.io.FileOutputStream.write(java.base@11/FileOutputStream.java:354)
        at java.io.BufferedOutputStream.flushBuffer(java.base@11/BufferedOutputStream.java:81)
        at java.io.BufferedOutputStream.flush(java.base@11/BufferedOutputStream.java:142)
        - locked <0x00000000847e2818> (a java.io.BufferedOutputStream)
        at java.io.PrintStream.write(java.base@11/PrintStream.java:561)
        - locked <0x0000000084718cc8> (a java.io.PrintStream)
        at sun.nio.cs.StreamEncoder.writeBytes(java.base@11/StreamEncoder.java:233)
        at sun.nio.cs.StreamEncoder.implFlushBuffer(java.base@11/StreamEncoder.java:312)
        at sun.nio.cs.StreamEncoder.flushBuffer(java.base@11/StreamEncoder.java:104)
        - locked <0x0000000084718c88> (a java.io.OutputStreamWriter)
        at java.io.OutputStreamWriter.flushBuffer(java.base@11/OutputStreamWriter.java:184)
        at java.io.PrintStream.newLine(java.base@11/PrintStream.java:625)
        - eliminated <0x0000000084718cc8> (a java.io.PrintStream)
        at java.io.PrintStream.println(java.base@11/PrintStream.java:883)
        - locked <0x0000000084718cc8> (a java.io.PrintStream)
        at TestClass.main(TestClass.java:7)

   Locked ownable synchronizers:
        - None

"Reference Handler" #2 daemon prio=10 os_prio=2 cpu=0.00ms elapsed=28.01s tid=0x00000245911b3000 nid=0x393c waiting on condition  [0x0000005b982ff000]
   java.lang.Thread.State: RUNNABLE
        at java.lang.ref.Reference.waitForReferencePendingList(java.base@11/Native Method)
        at java.lang.ref.Reference.processPendingReferences(java.base@11/Reference.java:241)
        at java.lang.ref.Reference$ReferenceHandler.run(java.base@11/Reference.java:213)

   Locked ownable synchronizers:
        - None

"Finalizer" #3 daemon prio=8 os_prio=1 cpu=0.00ms elapsed=28.01s tid=0x00000245911b4000 nid=0x434c in Object.wait()  [0x0000005b983fe000]
   java.lang.Thread.State: WAITING (on object monitor)
        at java.lang.Object.wait(java.base@11/Native Method)
        - waiting on <0x0000000084729c70> (a java.lang.ref.ReferenceQueue$Lock)
        at java.lang.ref.ReferenceQueue.remove(java.base@11/ReferenceQueue.java:155)
        - waiting to re-lock in wait() <0x0000000084729c70> (a java.lang.ref.ReferenceQueue$Lock)
        at java.lang.ref.ReferenceQueue.remove(java.base@11/ReferenceQueue.java:176)
        at java.lang.ref.Finalizer$FinalizerThread.run(java.base@11/Finalizer.java:170)

   Locked ownable synchronizers:
        - None

"Signal Dispatcher" #4 daemon prio=9 os_prio=2 cpu=0.00ms elapsed=27.90s tid=0x0000024591a43000 nid=0x3938 runnable  [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

   Locked ownable synchronizers:
        - None

"Attach Listener" #5 daemon prio=5 os_prio=2 cpu=62.50ms elapsed=27.90s tid=0x00000245911e9000 nid=0x28fc waiting on condition  [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

   Locked ownable synchronizers:
        - None

"C2 CompilerThread0" #6 daemon prio=9 os_prio=2 cpu=437.50ms elapsed=27.90s tid=0x00000245911eb800 nid=0x2e78 waiting on condition  [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE
   No compile task

   Locked ownable synchronizers:
        - None

"C1 CompilerThread0" #8 daemon prio=9 os_prio=2 cpu=187.50ms elapsed=27.90s tid=0x00000245911f2000 nid=0x4be0 waiting on condition  [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE
   No compile task

   Locked ownable synchronizers:
        - None

"Sweeper thread" #9 daemon prio=9 os_prio=2 cpu=15.63ms elapsed=27.88s tid=0x0000024591ab0000 nid=0x13b8 runnable  [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

   Locked ownable synchronizers:
        - None

"Common-Cleaner" #10 daemon prio=8 os_prio=1 cpu=0.00ms elapsed=27.66s tid=0x00000245f264d000 nid=0x40e4 in Object.wait()  [0x0000005b989ff000]
   java.lang.Thread.State: TIMED_WAITING (on object monitor)
        at java.lang.Object.wait(java.base@11/Native Method)
        - waiting on <0x000000008472a448> (a java.lang.ref.ReferenceQueue$Lock)
        at java.lang.ref.ReferenceQueue.remove(java.base@11/ReferenceQueue.java:155)
        - waiting to re-lock in wait() <0x000000008472a448> (a java.lang.ref.ReferenceQueue$Lock)
        at jdk.internal.ref.CleanerImpl.run(java.base@11/CleanerImpl.java:148)
        at java.lang.Thread.run(java.base@11/Thread.java:834)
        at jdk.internal.misc.InnocuousThread.run(java.base@11/InnocuousThread.java:134)

   Locked ownable synchronizers:
        - None

"Monitor Ctrl-Break" #11 daemon prio=5 os_prio=0 cpu=0.00ms elapsed=27.45s tid=0x0000024591d54000 nid=0x34b0 runnable  [0x0000005b98afe000]
   java.lang.Thread.State: RUNNABLE
        at java.net.SocketInputStream.socketRead0(java.base@11/Native Method)
        at java.net.SocketInputStream.socketRead(java.base@11/SocketInputStream.java:115)
        at java.net.SocketInputStream.read(java.base@11/SocketInputStream.java:168)
        at java.net.SocketInputStream.read(java.base@11/SocketInputStream.java:140)
        at sun.nio.cs.StreamDecoder.readBytes(java.base@11/StreamDecoder.java:284)
        at sun.nio.cs.StreamDecoder.implRead(java.base@11/StreamDecoder.java:326)
        at sun.nio.cs.StreamDecoder.read(java.base@11/StreamDecoder.java:178)
        - locked <0x000000008471f758> (a java.io.InputStreamReader)
        at java.io.InputStreamReader.read(java.base@11/InputStreamReader.java:185)
        at java.io.BufferedReader.fill(java.base@11/BufferedReader.java:161)
        at java.io.BufferedReader.readLine(java.base@11/BufferedReader.java:326)
        - locked <0x000000008471f758> (a java.io.InputStreamReader)
        at java.io.BufferedReader.readLine(java.base@11/BufferedReader.java:392)
        at com.intellij.rt.execution.application.AppMainV2$1.run(AppMainV2.java:55)

   Locked ownable synchronizers:
        - None

"Service Thread" #12 daemon prio=9 os_prio=0 cpu=0.00ms elapsed=27.45s tid=0x0000024591d2d800 nid=0x3abc runnable  [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

   Locked ownable synchronizers:
        - None

"VM Thread" os_prio=2 cpu=31.25ms elapsed=28.03s tid=0x00000245911af000 nid=0x41dc runnable

"GC Thread#0" os_prio=2 cpu=0.00ms elapsed=28.19s tid=0x00000245f2583000 nid=0x3708 runnable

"GC Thread#1" os_prio=2 cpu=0.00ms elapsed=25.42s tid=0x0000024591dfd800 nid=0x223c runnable

"GC Thread#2" os_prio=2 cpu=0.00ms elapsed=25.42s tid=0x0000024591dfe000 nid=0x3e60 runnable

"G1 Main Marker" os_prio=2 cpu=0.00ms elapsed=28.18s tid=0x00000245f25b1800 nid=0x4a5c runnable

"G1 Conc#0" os_prio=2 cpu=0.00ms elapsed=28.18s tid=0x00000245f25b4800 nid=0x3378 runnable

"G1 Refine#0" os_prio=2 cpu=0.00ms elapsed=28.18s tid=0x00000245f2644000 nid=0x1e0c runnable

"G1 Young RemSet Sampling" os_prio=2 cpu=0.00ms elapsed=28.18s tid=0x00000245f2647000 nid=0x4054 runnable
"VM Periodic Task Thread" os_prio=2 cpu=0.00ms elapsed=27.45s tid=0x0000024591d93000 nid=0x2c64 waiting on condition

JNI global refs: 15, weak refs: 0

线程中参数解释:
tid: Java memory address of its internal Thread control structure. 16进制的
nid: native thread id. 每一个nid对应于linux下的一个tid, 即lwp (light weight process, or thread). 16进制的,转到10进制后可以用ps命令找到它。
prio: java内定义的线程的优先级
os_prio: 操作系统级别的优先级
cpu: 为cpu运行时间
elapsed: 为实际运行时间
daemon: 说明是守护线程

  • JvisualVm

VisualVM是一款免费的\集成了多个JDK命令行工具的可视化工具,是功能最强大的运行监控和故障处理程序之一,曾经很长一段时间是oracle官方主力发展的虚拟机故障处理工具。功能包括生成和分析海量数据、跟踪内存泄漏、监控垃圾回收器、执行内存和CPU分析,同时它还支持在MBeans上进行浏览和操作。可以基于该工具实现线程转储和可视化监测。

参考:
《Java多线程编程实战指南》黄文海
jvm监控工具小结

线程安全问题的三个方面

线程安全问题概括来说表现为3个方面:原子性、可见性和有序性。

原子性

原子操作的“不可分割”包括以下两层含义。

  • 访问(读、写)某个共享变量的操作从其执行线程以外的任何线程来看,该操作要么已经执行结束要么尚未发生,即其他线程不会“看到”该操作执行了部分的中间效果。
  • 访问同一组共享变量的原子操作是不能够被交错的。

Java中有两种方式来实现原子性。一种是使用锁(Lock)。锁具有排他性,即它能够保障一个共享变量在任意一个时刻只能够被一个线程访问。这就排除了多个线程在同一时刻访问同一个共享变量而导致干扰与冲突的可能,即消除了竞态。另一种是利用处理器提供的专门CAS(Compare-and-Swap)指令,CAS算作乐观锁。

Java语言中针对任何变量的读操作都是原子操作。在Java语言中,long型和double型以外的任何类型的变量的写操作都是原子操作。对long/double型变量的写操作由于Java语言规范并不保障其具有原子性,因此在多个线程并发访问同一long/double型变量的情况下,一个线程可能会读取到其他线程更新该变量的“中间结果”。尽管如此,Java语言规范特别地规定对于volatile关键字修饰的long/double型变量的写操作具有原子性。

可见性

可见性就是指一个线程对共享变量的更新的结果对于读取相应共享变量的线程而言是否可见的问题。多线程程序在可见性方面存在问题意味着某些线程读取到了旧数据(StaleData)。导致可见性问题的原因分为两种,一种是JIT编译器的优化,需要基于一定机制避免多线程情况下的不正常编译优化;另一种是没有及时进行缓存同步,要通过使更新共享变量的处理器执行冲刷处理器缓存的动作,并使读取共享变量的处理器执行刷新处理器缓存的动作来保障可见性。

可见性的保障仅仅意味着一个线程能够读取到共享变量的相对新值,而不能保障该线程能够读取到相应变量的最新值,即读到数据后到使用的时候,原来的数据可能已经发生了变化。

有序性

多种因素都可能导致程序的感知顺序与源代码顺序不一致,而这种不一致可能导致线程安全问题。避免这个问题实质上就是保证感知顺序与源代码顺序一致,即有序性。

导致有序性问题的来源分为:(1)指令重排序。指令重排序主要来源于JIT的编译优化和处理器在判断语句场景的猜测执行技术;(2)存储系统重排序。即使在处理器严格依照程序顺序执行两个内存访问操作的情况下,在存储子系统的作用下其他处理器对这两个操作的感知顺序仍然可能与程序顺序不一致,即这两个操作的执行顺序看起来像是发生了变化。这种现象就是存储子系统重排序,也被称为内存重排序(MemoryOrdering)。

单线程也会发生重排序,但是结果不会出现异常,就仿佛是串行执行的一样;要保证多线程的有序性,需要在逻辑上部分禁止重排序。

参考:
《Java多线程编程实战指南》黄文海

Thread类中的start和run方法的区别是什么?

Thread类的start方法的作用是启动相应的线程,并在这个新线程中执行run方法,线程属于“一次性用品”,start方法也只能够被调用一次,多次调用同一个Thread实例的start方法会导致其抛出IllegalThreadStateException异常。

Thread类的run方法可以反复执行,但是是在当前线程中执行,不会创建新线程,一般不建议这样操作。

参考:
《Java多线程编程实战指南》黄文海

Runnable和Callable?Future的作用是什么?

Runnable和Callable

Runnable接口可以被看作对任务进行的抽象,任务的处理逻辑就体现在run方法之中。Thread类实际上是Runnable接口的一个实现类,其对Runnable接口的实现。

Callable接口也是对任务的抽象,任务的处理逻辑可以在Callable接口实现类的call方法中实现。Callable接口相当于一个增强型的Runnable接口:call方法的返回值代表相应任务的处理结果,其类型V是通过Callable接口的类型参数指定的;call方法代表的任务在其执行过程中可以抛出异常。而Runnable接口中的run方法既无返回值也不能抛出异常。

采用Runnable实例来表示异步任务,其优点是任务既可以交给一个专门的工作者线程执行(以相应的Runnable实例为参数创建并启动一个工作者线程),也可以交给一个线程池或者Executor的其他实现类来执行;其缺点是我们无法直接获取任务的执行结果。使用Callable实例来表示异步任务,其优点是我们可以通过ThreadPoolExecutor.submit(Callable)的返回值获取任务的处理结果;其缺点是Callable实例表示的异步任务只能交给线程池执行,而无法直接交给一个专门的工作者线程或者Executor实现类执行。

Future

Future接口实例可被看作任务的处理结果句柄(Handle),Future.get()方法可以用来获取task参数所指定的任务的处理结果,Future.get()是个阻塞方法,该方法能够抛出InterruptedException说明它可以响应线程中断,可以通过捕获Future.get()调用抛出的异常来知晓相应任务执行过程中抛出的异常。ThreadPoolExecutor线程池的一个submit方法声明如下:publicFuturesubmit(Callabletask),可以通过提交Callable任务并通过Future.get()获取结果。

java.util.concurrent.FutureTask类融合了Runnable接口和Callable接口的优点:FutureTask是java.util.concurrent.RunnableFuture接口的一个实现类,由于RunnableFuture接口继承了Future接口和Runnable接口,因此FutureTask既是Runnable接口的实现类也是Future接口的实现。因此FutureTask表示的异步任务可以交给专门的工作者线程执行,也可以交给Executor实例(比如线程池)执行,FutureTask还能够直接返回其代表的异步任务的处理结果。ThreadPoolExecutor.submit(Callabletask)的返回值就是一个FutureTask实例。

FutureTask的一个构造器可以将Callable实例转换为Runnable实例,该构造器的声明如下:publicFutureTask(Callablecallable)。
我们可以将任务的处理逻辑封装在一个Callable实例中,并以该实例为参数创建一个FutureTask实例,我们可以用FutureTask实例(Runnable实例)为参数来创建并启动一个工作者线程以执行相应的任务,也可以将FutureTask实例交给Executor执行(通过Executor.execute(Runnabletask)调用),FutureTask类还实现了Future接口,这使得我们在调用Executor.execute(Runnabletask)这样只认Runnable接口的方法来执行任务的情况下依然能够获取任务的执行结果。

参考:
《Java多线程编程实战指南》黄文海

标签:11,java,prio,Thread,面经,base,线程,多线程
From: https://www.cnblogs.com/fattree/p/18253283

相关文章

  • 面经梳理--java
    题目Java创建一个对象的方法有几种?使用new关键字反射(1)使用Class类的newInstance方法,只能无参构造器Employeeemp2=(Employee)Class.forName("org.programming.mitra.exercises.Employee").newInstance();或者(目前Class.newInstance()这种方法因为效率问题已经被标记@......
  • 45.JavaScript基础【三】
    【一】JavaScript之函数1)函数声明函数须先声明,才能使用函数声明时不会立即执行,只有调用时才会执行function函数名(参数1,参数2){ 代码体}2)函数调用函数名()函数的执行与定位位置无关,只与调用位置有关可多次调用,每次调用都是独立不相关的3)函数分类1.无......
  • 44.JavaScript基础【二】
    【一】JavaScript之运算符1)算术运算符加法:+减法:-乘法:*除法:/优先运算:()取余:%特殊NaNNaN参与的运算结果全是NaN隐式转化null转成0undefined转成NaN2)比较运算符>大于<小于<=小于等于>=大于等于==相等!=不相等===全等与相等区别在于会判断数据......
  • 43.JavaScript基础【一】
    【一】JavaScript1)介绍也是一门编程语言,他可以写后端代码JS是由ECMAScript、DOM、BOM组成JS是运行在浏览器脚本的语言2)注释语法//单行注释/*多行注释多行注释*/3)js代码的书写位置head头里面的script标签中写在body体最下面直接常见一个js脚本文件,......
  • 47.JavaScript基础【五】
    【一】什么是jQuery1)概述是一个轻量的、兼容多浏览器的JavaScript的第三方库其内部封装了JS代码、能通过更少的代码操作DOM对象提高了代码效率、简化了代码量2)优势轻量级的JS框架丰富的DOM选择器链式表达式事件、样式、动画支持Ajax操作支持跨浏览器兼容插件扩展开......
  • 46.JavaScript基础【四】
    【一】弹出框是网页开发中常用的交互组件,用于显示警告、确认或提示,并于用户进行交互1)警告框用于向用户显示一条重要的警告信息通常包含一个确认按钮用于关闭alert("警告提示框")2)确认框用于向用户询问一个问题或确认某个操作通常包含一个确认按钮和一个取消......
  • javab每日一题:在spring里有哪些常用注解?
     Spring框架提供了许多注解,用于简化配置、管理Bean、处理事务、处理AOP等。以下是一些在Spring中常用的注解以及它们的作用:@ComponentScan:作用:用于启用组件扫描,指定要扫描的基础包。Spring会自动扫描并注册带有@Component及其派生注解(@Service、@Repository、@Controller......
  • Java8的stream流让操作集合更容易
    概述好久不见,最近忙于工作,好久没有发文章了,入职大公司,发现有些同事更喜欢使用stream流操作集合,故而自己也研究学习一下。事先声明:我并非原创,我只是学习并整理的大佬们的文章,原文章放在最后,有兴趣的可以去看看Java8提供了Stream(流)处理集合的关键抽象概念,Stream使用一种类似用SQ......
  • JAVA 实用类总结
    1.什么是枚举类?访问修饰符Enum枚举名称{}其应用上可以看做一个类去定义,如果枚举里有方法,定义的枚举常量要以':'结尾2.应用枚举的好处?枚举限制了范围,更加安全,如果要大量定义常量用publicfinalstaticA=1;定义起来太复杂,用枚举简单多,代码简洁publicvoidday(Day(枚举类型)......
  • Java课程设计:基于Javaweb的校园订餐系统
    文章目录一、项目介绍二、项目技术栈三、核心代码四、项目展示五、源码获取一、项目介绍在当今互联网高速发展的时代,大学校园内的学生生活正在发生着翻天覆地的变化。其中,校园内的餐饮服务无疑是亟需改革和创新的领域之一。传统的校园食堂模式,往往存在就餐高峰时......