多线程

  • 多线程基础概念
    • 什么是多线程
    • 多线程的好处和劣势
    • 什么是线程上下文切换
    • 什么是守护线程和用户线程
  • 多线程的实现
    • 线程的状态(线程的生命周期)
    • 创建线程的四种方式
      • 继承 Thread 类
      • 实现 Runnable 接口
      • 实现 Callable 接口
      • 使用匿名内部类方式
  • 多线程中的接口或者方法介绍
    • 多线程的常用方法
    • runnable,callable以及Future,FutureTask介绍
      • runnable和callable有什么区别
      • 什么是 Callable 和 Future(接口,异步运算的返回值)
      • 什么是 FutureTask(类,异步运算的任务)
    • run()和start()
      • 线程的run()和start()有什么区别?
      • 为什么调用 start() 方法时会执行 run() 方法,而不能直接调用run() 方法?
    • wait() sleep() yield () notify() notifyAll()
      • 你是如何调用 wait() 方法的?循环调用
      • Thread 类中的 yield() 方法有什么作用
      • sleep() 和 wait() 有什么区别
      • 线程的 sleep()方法和 yield()方法有什么区别
      • 为什么 Thread 类的 sleep()和 yield ()方法是静态的
      • notify() 和 notifyAll() 有什么区别?
      • 请说出与线程同步以及线程调度相关的方法
      • 为什么 wait(), notify()和 notifyAll()必须在同步方法或者同步块中被调用
      • 为什么线程通信的方法 wait(), notify()和 notifyAll()被定义在 Object 类
  • 线程停止,阻塞,中断
    • 如何停止一个正在运行的线程
    • 你如何确保main()方法所在的线程是Java程序最后结束的线程
    • Java 中 interrupted 和 isInterrupted 方法的区别
    • 什么是阻塞式方法sleep wait
    • Java 中你怎样唤醒一个阻塞的线程wait()、notify()
  • 线程调度
    • Java 中用到的线程调度算法是什么
    • 线程的调度策略以及可能终止线程的运行的情况
    • 线程调度器(Thread Scheduler)和时间分片(Time Slicing )
  • 线程安全
    • 什么叫线程安全
    • 在 Java 程序中怎么保证多线程的运行安全
    • servlet 是线程安全
  • 线程优先级
  • 线程异常
    • 一个线程运行时发生异常会怎样
    • Java 线程数过多会造成什么异常(线程OutOfMemoryError 异常)
  • 线程类的构造方法、静态块是被哪个线程调用的

多线程基础概念

什么是多线程

多线程:多线程是指程序中包含多个执行流,即在一个程序中可以同时运行多个不同的线程来执行不同的任务

多线程的好处和劣势

好处:

  • 可以提高 CPU 的利用率。在多线程程序中,一个线程必须等待的时候,CPU 可以运行其它的线程而不是等待,这样就大大提高了程序的效率。也就是说允许单个程序创建多个并行执行的线程来完成各自的任务。

劣势:

  • 线程也是程序,所以线程需要占用内存,线程越多占用内存也越多;
  • 多线程需要协调和管理,所以需要 CPU 时间跟踪线程;
  • 线程之间对共享资源的访问会相互影响,必须解决竞用共享资源的问题

什么是线程上下文切换

当前任务在执行完 CPU 时间片切换到另一个任务之前会先保存自己的状态,以便下次再切换回这个任务时,可以再加载这个任务的状态。任务从保存到再加载的过程就是一次上下文切换。

什么是守护线程和用户线程

  • 用户线程:当我们在Java程序中创建一个线程,它就被称为用户线程。
  • 守护线程:守护线程是在后台执行并且不会阻止JVM终止的线程。当没有用户线程在运行的时候,JVM关闭程序并且退出。一个守护线程创建的子线程依然是守护线程
    后台线程(守护线程或者叫精灵线程)属性方法setDaemon(true)

多线程的实现

线程的状态(线程的生命周期)

  • 新建(new)新创建了一个线程对象
  • 就绪(可运行状态)(runnable):线程对象创建后,当调用线程对象的 start()方法,该线程处于就绪状态,等待被线程调度选中,获取cpu的使用权。
  • 运行(running)可运行状态(runnable)的线程获得了cpu时间片(timeslice)执行程序代码
    注:就绪状态是进入到运行状态的唯一入口,也就是说,线程要想进入运行状态执行,首先必须处于就绪状态中;
  • 阻塞(block)处于运行状态中的线程由于某种原因,暂时放弃对 CPU的使用权,停止执行,此时进入阻塞状态,直到其进入到就绪状态,才 有机会再次被 CPU 调用以进入到运行状态。
    阻塞的情况分三种:
    (一). 等待阻塞:运行状态中的线程执行 wait()方法,JVM会把该线程放入等待队列(waitting
    queue)中,使本线程进入到等待阻塞状态;(主动阻塞)
    (二). 同步阻塞:线程在获取 synchronized 同步锁失败(因为锁被其它线程所占用),则JVM
    会把该线程放入锁池(lock pool)中,线程会进入同步阻塞状态;
    (三). 其他阻塞: 通过调用线程的 sleep()或 join()或发出了 I/O 请求时,线程会进入到阻塞状
    态。当 sleep()状态超时、join()等待线程终止或者超时、或者 I/O 处理完毕时,线程重新转入
    就绪状态
  • 死亡(dead)(结束)线程run()、main()方法执行结束,或者因异常退出了run()方法,则该线程结束生命周期死亡的线程不可再次复生。

创建线程的四种方式

继承 Thread 类

 public class MyThread extends Thread {@Overridepublic void run() {System.out.println(Thread.currentThread().getName() + " run()方法正在执行...");}

实现 Runnable 接口

 public class MyRunnable implements Runnable {@Overridepublic void run() {System.out.println(Thread.currentThread().getName() + " run()方法执行中...");}

实现 Callable 接口

 public class MyCallable implements Callable<Integer> {@Overridepublic Integer call() {System.out.println(Thread.currentThread().getName() + " call()方法执行中...");return 1;}}

使用匿名内部类方式

在我们需要创建多线程的地方 创建一个匿名内部类,类里面创建Therad类,new Runnable()接口
Thread thread = new Thread(new Runnable()

 public class CreateRunnable {public static void main(String[] args) {//创建多线程创建开始Thread thread = new Thread(new Runnable() {public void run() {for (int i = 0; i < 10; i++) {System.out.println("i:" + i);}}});thread.start();}}

多线程中的接口或者方法介绍

多线程的常用方法

方法名 描述
sleep() 强迫一个线程睡眠N毫秒
isAlive() 判断一个线程是否存活。
join() 等待线程终止。
activeCount() 程序中活跃的线程数。
enumerate() 枚举程序中的线程。
currentThread() 得到当前线程。
isDaemon() 一个线程是否为守护线程。
setDaemon() 设置一个线程为守护线程。
setName() 为线程设置一个名称。
wait() 强迫一个线程等待。
notify() 通知一个线程继续运行。
setPriority() 设置一个线程的优先级。

runnable,callable以及Future,FutureTask介绍

runnable和callable有什么区别

相同点
①都是接口
②都可以编写多线程程序
③都采用Thread.start()启动线程
主要区别
①Runnable 接口 run 方法无返回值;Callable 接口 call 方法有返回值,是个泛型,和Future、
②FutureTask配合可以用来获取异步执行的结果
③Runnable 接口 run 方法只能抛出运行时异常,且无法捕获处理;Callable 接口 call 方法允许抛出异常,可以获取异常信息
注:Callalbe接口支持返回执行结果,需要调用FutureTask.get()得到,此方法会阻塞主进程的继续往下执行,如果不调用不会阻塞

什么是 Callable 和 Future(接口,异步运算的返回值)

Callable 接口类似于 Runnable,从名字就可以看出来了,但是 Runnable 不会返回结果,并且无法抛出返回结果的异常,而 Callable 功能更强大一些,被线程执行后,可以返回值,这个返回值可以被 Future 拿到,也就是说,Future接口 可以拿到异步执行任务的返回值。Future 接口表示异步任务,是一个可能还没有完成的异步任务的结果。所以说 Callable用于产生结果,Future 用于获取结果。

什么是 FutureTask(类,异步运算的任务)

FutureTask 表示一个异步运算的任务。FutureTask 里面可以传入一个 Callable 的具体实现类,可以对这个异步运算的任务的结果进行等待获取、判断是否已经完成、取消任务等操作。只有当运算完成的时候结果才能取回,如果运算尚未完成 get 方法将会阻塞。一个FutureTask 对象可以对调用了 Callable 和 Runnable 的对象进行包装,由于 FutureTask 也是Runnable 接口的实现类,所以 FutureTask 也可以放入线程池中

run()和start()

线程的run()和start()有什么区别?

每个线程都是通过某个特定Thread对象所对应的方法run()来完成其操作的,run()方法称为线程
体。通过调用Thread类的start()方法来启动一个线程。
start() 方法用于启动线程,run() 方法用于执行线程的运行时代码。run() 可以重复调用,而 start()只能调用一次。
start()方法来启动一个线程,真正实现了多线程运行。调用start()方法无需等待run方法体代码执行完毕,可以直接继续执行其他的代码; 此时线程是处于就绪状态,并没有运行。 然后通过此Thread类调用方法run()来完成其运行状态, run()方法运行结束, 此线程终止。然后CPU再调度其它线程。
run()方法是在本线程里的,只是线程里的一个函数,而不是多线程的。 如果直接调用run(),其实就相当于是调用了一个普通函数而已,直接待用run()方法必须等待run()方法执行完毕才能执行下面的代码,所以执行路径还是只有一条,根本就没有线程的特征,所以在多线程执行时要使用start()方法而不是run()方法

为什么调用 start() 方法时会执行 run() 方法,而不能直接调用run() 方法?

  • new 一个 Thread,线程进入了新建状态。调用 start() 方法,会启动一个线程并使线程进入了就绪状态,当分配到 时间片 后就可以开始运行了。 start() 会执行线程的相应准备工作,然后自动执行run() 方法的内容,这是真正的多线程工作。
  • 而直接执行 run() 方法,会把 run 方法当成一个 main 线程下的普通方法去执行,并不会在某个线程中执行它,所以这并不是多线程工作。
    总结: 调用 start 方法方可启动线程并使线程进入就绪状态,而 run 方法只是 thread 的一个普通方法调用,还是在主线程里执行

wait() sleep() yield () notify() notifyAll()

你是如何调用 wait() 方法的?循环调用

wait() 方法应该在,因为当线程获取到 CPU 开始执行的时候,其他条件可能还没有满足,所以在处理前,循环检测条件是否满足会更好。下面是一段标准的使用 wait 和 notify 方法的代码:

 synchronized (monitor) {// 判断条件谓词是否得到满足while(!locked) {// 等待唤醒monitor.wait();}// 处理其他的业务逻辑}

Thread 类中的 yield() 方法有什么作用

使当前线程从执行状态(运行状态)变为可执行态(就绪状态)
当前线程到了就绪状态,那么接下来哪个线程会从就绪状态变成执行状态呢?可能是当前线程,也可能是其他线程,看系统的分配了

sleep() 和 wait() 有什么区别

两者都可以暂停线程的执行

  • 类的不同:sleep() 是 Thread线程类的静态方法,wait() 是 Object类的方法。是否释放锁: sleep() 不释放锁;wait() 释放锁。
  • 用途不同:Wait 通常被用于线程间交互/通信,sleep 通常被用于暂停执行。
  • 用法不同:wait() 方法被调用后,线程不会自动苏醒,需要别的线程调用同一个对象上的 notify()或者 notifyAll() 方法,或者可以使用wait(longtimeout)超时后线程会自动苏醒。sleep() 方法执行完成后,线程会自动苏醒

线程的 sleep()方法和 yield()方法有什么区别

  • sleep()方法给其他线程运行机会时不考虑线程的优先级,因此会给低优先级的线程以运行的机会;yield()方法只会给相同优先级或更高优先级的线程以运行的机会;
  • 线程执行 sleep()方法后转入阻塞(blocked)状态,而执行 yield()方法后转入就绪状态
  • sleep()方法声明抛出 InterruptedException,而 yield()方法没有声明任何异常;
  • sleep()方法比 yield()方法(跟操作系统 CPU 调度相关)具有更好的可移植性,通常不建议
    使用yield()方法来控制并发线程的执行

为什么 Thread 类的 sleep()和 yield ()方法是静态的

①Thread 类的 sleep()和 yield()方法将在当前正在执行的线程上从运行状态变成就绪状态,其他正在处于等待的线程调用这些方法是没有意义的
②如果sleep和yield是实例方法,那就热闹了。一个线程可以获取其他线程对象的引用,然后通过引用调要其他线程的sleep和yield方法,让其他线程让出CPU使用权。如果每个线程都可以通过sleep、yield其他线程的方式来让自己获得CPU使用权,那不是世界大乱了。线程之间可以互相sleep,互相yield

1、sleep是静态方法,那么在实现Runnable的线程类也能调用。
2、sleep是静态方法,所以sleep时候只是让出了cup却不能释对象锁,因为获取不到对象
3、线程和实例并不是对等的,不是一个线程是一个实例,是你创建的实例继承了Thread或者Runable,实现了run(),并调用start()的时候能执行多个线程,实例还是一个,线程却是多个。所以实例休眠线程就休眠了这个假设不成立。
如果sleep不是静态的, 只对当前进程作用. 而是实例方法, 那么应该和suspend有同样的问题, 死锁

notify() 和 notifyAll() 有什么区别?

如果线程调用了对象的 wait()方法,那么线程便会处于该对象的等待池中,等待池中的线程不会去
竞争该对象的锁。
notifyAll() 会唤醒所有的线程,notify() 只会唤醒一个线程
notifyAll() 调用后,会将全部线程由等待池移到锁池,然后参与锁的竞争,竞争成功则继续执行,
如果不成功则留在锁池等待锁被释放后再次参与竞争。而 notify()只会唤醒一个线程,具体唤醒哪
一个线程由虚拟机控制

请说出与线程同步以及线程调度相关的方法

(1) wait():使一个线程处于等待(阻塞)状态,并且释放所持有的对象的锁
(2)sleep():使一个正在运行的线程处于睡眠状态,是一个静态方法,调用此方法要处理
InterruptedException 异常;
(3)notify():唤醒一个处于等待状态的线程,当然在调用此方法的时候,并不能确切的唤醒某一
个等待状态的线程,而是由 JVM 确定唤醒哪个线程,而且与优先级无关;
(4)notityAll():唤醒所有处于等待状态的线程,该方法并不是将对象的锁给所有线程,而是让它
们竞争,只有获得锁的线程才能进入就绪状态;

为什么 wait(), notify()和 notifyAll()必须在同步方法或者同步块中被调用

因为线程持有对象的锁的所属问题
当一个线程需要调用对象的 wait()方法的时候,这个线程必须拥有该对象的锁,接着它就会释放这个对象锁并进入等待状态直到其他线程调用这个对象上的 notify()方法。同样的,当一个线程需要调用对象的 notify()方法时,它会释放这个对象的锁,以便其他在等待的线程就可以得到这个对象锁。
由于所有的这些方法都需要线程持有对象的锁,这样就只能通过同步来实现,所以他们只能在同步方法或者同步块中被调用

为什么线程通信的方法 wait(), notify()和 notifyAll()被定义在 Object 类

①Java的每个对象中都有一个锁(monitor,也可以成为监视器)
②wait(),notify()等方法用于等待对象的锁或者通知其他线程对象的监视器可用
在Java的线程中并没有可供任何对象使用的锁和同步器。这些方法是Object类的一部分,这样Java的每一个类都有用于线程间通信的基本方法

线程停止,阻塞,中断

如何停止一个正在运行的线程

  • 线程正常退出,也就是当run方法完成后线程终止。
  • 使用interrupt方法中断线程
  • 进程的停止:(任务管理器结束进程)
    当一个进程中所有的前台线程停止后,该进行就结束

你如何确保main()方法所在的线程是Java程序最后结束的线程

我们可以使用Thread类的joint()方法来确保所有程序创建的线程在main()方法退出前结束

Java 中 interrupted 和 isInterrupted 方法的区别

  • interrupt:用于中断线程。调用该方法的线程的状态为将被置为”中断”状态。
    注意:线程中断仅仅是置线程的中断状态位,不会停止线程。需要用户自己去监视线程的状态为并做处理。支持线程中断的方法(也就是线程中断后会抛出interruptedException 的方法)就是在监视线程的中断状态,一旦线程的中断状态被置为“中断状态”,就会抛出中断异常。
  • interrupted:是静态方法,查看当前中断信号是true还是false并且清除中断信号。如果一个线程被中断了,第一次调用 interrupted 则返回 true,第二次和后面的就返回 false 了
  • isInterrupted:是可以返回当前中断信号是true还是false,与interrupt最大的差别

什么是阻塞式方法sleep wait

阻塞式方法是指程序会一直等待该方法完成期间不做其他事情,ServerSocket 的accept()方法就是一直等待客户端连接。这里的阻塞是指调用结果返回之前,当前线程会被挂起,直到得到结果之后才会返回。此外,还有异步和非阻塞式方法在任务完成前就返回
sleep wait 都是多线程里面的阻塞方法

Java 中你怎样唤醒一个阻塞的线程wait()、notify()

首先 ,wait()、notify() 方法是针对对象的,调用任意对象的 wait()方法都将导致线程阻塞,阻塞
的同时也将释放该对象的锁,相应地,调用任意对象的 notify()方法则将随机解除该对象阻塞的线
程,但它需要重新获取该对象的锁,直到获取成功才能往下执行;
其次,wait、notify 方法必须在 synchronized 块或方法中被调用,并且要保证同步块或方法的锁
对象与调用 wait、notify 方法的对象是同一个,如此一来在调用 wait 之前当前线程就已经成功获
取某对象的锁,执行 wait 阻塞后当前线程就将之前获取的对象锁释放

线程调度

Java 中用到的线程调度算法是什么

Java是由JVM中的线程计数器来实现线程调度分配CPU 的使用权
有两种调度模型:分时调度模型和抢占式调度模型。

  • 分时调度模型是指让所有的线程轮流获得 cpu 的使用权,并且平均分配每个线程占用的 CPU
    的时间片这个也比较好理解。
  • Java虚拟机采用抢占式调度模型,是指优先让可运行池中优先级高的线程占用CPU,如果可
    运行池中的线程优先级相同,那么就随机选择一个线程,使其占用CPU。处于运行状态的线
    程会一直运行,直至它不得不放弃 CPU。

线程的调度策略以及可能终止线程的运行的情况

线程调度器选择优先级最高的线程运行,但是,如果发生以下情况,就会终止线程的运行:
(1)线程体中调用了 yield 方法让出了对 cpu 的占用权利
(2)线程体中调用了 sleep 方法使线程进入睡眠状态
(3)线程由于 IO 操作受到阻塞(就是当客户端的数据从网卡缓冲区复制到内核缓冲区之前,服务端会一直阻塞)
(4)另外一个更高优先级线程出现
(5)在支持时间片的系统中,该线程的时间片用完

线程调度器(Thread Scheduler)和时间分片(Time Slicing )

线程调度器是一个操作系统服务,它负责为 Runnable 状态的线程分配 CPU 时间。一旦我们创建一个线程并启动它,它的执行便依赖于线程调度器的实现。
时间分片是指将可用的 CPU 时间分配给可用的 Runnable 线程的过程。分配 CPU 时间可以基于线程优先级或者线程等待的时间。线程调度并不受到 Java 虚拟机控制,所以由应用程序来控制它是更好的选择(也就是说不要让你的程序依赖于线程的优先级)

线程安全

什么叫线程安全

多线程并发访问同一个资源,会产生线程安全的问题
线程安全是编程中的术语,指某个方法在多线程环境中被调用时,能够正确地处理多个线程之间的共享变量,使程序功能正确完成

在 Java 程序中怎么保证多线程的运行安全

方法一:使用安全类,比如 java.util.concurrent 下的类,使用原子类AtomicInteger
归功于AtomicInteger.incrementAndGet()方法的原子性
方法二:使用自动锁 synchronized
方法三:使用手动锁 Lock
手动锁 Java 示例代码如下:
Lock lock = new ReentrantLock();
lock. lock();
try {
System. out. println(“获得锁”);
} catch (Exception e) {
// TODO: handle exception
} finally {
System. out. println(“释放锁”);
lock. unlock();
}

servlet 是线程安全

Servlet 不是线程安全的,servlet 是单实例多线程的,当多个线程同时访问同一个方法,是不能保证共享变量的线程安全性的。
Struts2 的 action 是多实例多线程的,是线程安全的,每个请求过来都会 new 一个新的 action 分
配给这个请求,请求完成后销毁。
SpringMVC 的 Controller 是线程安全的吗?不是的,和 Servlet 类似的处理流程。
Struts2 好处是不用考虑线程安全问题;Servlet 和 SpringMVC 需要考虑线程安全问题,但是性能
可以提升不用处理太多的 gc,可以使用 ThreadLocal 来处理多线程的问题。

线程优先级

每一个线程都是有优先级的,一般来说,高优先级的线程在运行时会具有优先权,但这依赖于线程调度的实现,这个实现是和操作系统相关的(OS dependent)。我们可以定义线程的优先级,但是这并不能保证高优先级的线程会在低优先级的线程前执行。线程优先级是一个 int 变量(从 1-10),1 代表最低优先级,10 代表最高优先级。
Java 的线程优先级调度会委托给操作系统去处理,所以与具体的操作系统优先级有关,如非特别
需要,一般无需设置线程优先级。
当然,如果你真的想设置优先级可以通过setPriority()方法设置,但是设置了不一定会该变,这个
是不准确的

线程异常

一个线程运行时发生异常会怎样

如果异常没有被捕获该线程将会停止执行。Thread.UncaughtExceptionHandler是用于处理未捕获异常造成线程突然中断情况的一个内嵌接口。当一个未捕获异常将造成线程中断的时候,JVM会使用 Thread.getUncaughtExceptionHandler()来查询线程的 UncaughtExceptionHandler 并将线程和异常作为参数传递给 handler 的 uncaughtException()方法进行处理

Java 线程数过多会造成什么异常(线程OutOfMemoryError 异常)

  • 线程的生命周期开销非常高
  • 消耗过多的 CPU资源,如果可运行的线程数量多于可用处理器的数量,那么有线程将会被闲置。大量空闲的线程会占用许多内存,给垃圾回收器带来压力,而且大量的线程在竞争 CPU资源时还将产生其他性能的开销。
  • 降低稳定性JVM,在可创建线程的数量上存在一个限制,这个限制值将随着平台的不同而不同,并且承受着多个因素制约,包括 JVM 的启动参数、Thread 构造函数中请求栈的大小,以及底层操作系统对线程的限制等。如果破坏了这些限制,那么可能抛出OutOfMemoryError 异常

线程类的构造方法、静态块是被哪个线程调用的

这是一个非常刁钻和狡猾的问题。请记住:线程类的构造方法、静态块是被 new这个线程类所在的线程所调用的,而 run 方法里面的代码才是被线程自身所调用的
如果说上面的说法让你感到困惑,那么我举个例子,假设 Thread2 中 new 了Thread1,main 函
数中 new 了 Thread2,那么:
(1)Thread2 的构造方法、静态块是 main 线程调用的,Thread2 的 run()方法是Thread2 自己调用的
(2)Thread1 的构造方法、静态块是 Thread2 调用的,Thread1 的 run()方法是Thread1 自己调用的


Java基础-多线程相关推荐

  1. java基础-多线程应用案例展示

    java基础-多线程应用案例展示 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.两只熊,100只蜜蜂,蜜蜂每次生产的蜂蜜量是1,罐子的容量是30,熊在罐子的蜂蜜量达到20的时候 ...

  2. 2020 - [Java基础 +多线程 + 虚拟机] + [计网 + 操作系统] + [MySQL] + [Redis] + [RocketMQ] + [Spring]常见面试题与解析

    前情提要:下面的内容主要由网上的资料和个人的理解整理而成.由于时间仓促可能没有给出相应的链接,并不代表我不尊重他人的劳动成果,后续更新会补上相应的链接.其中内容可能有理解不到位的地方,大家可选择性采纳 ...

  3. Java基础--多线程

    一.程序.进程.线程 1.区别 (1)程序是一段静态的代码,为应用程序执行的蓝本. (2)进程为程序的一次动态执行过程,包括代码的加载.执行以及执行完毕的一个完整过程. (3)线程是进程中的一个执行单 ...

  4. 黑马程序员——java基础---多线程(二)

    ------Java培训.Android培训.iOS培训..Net培训.期待与您交流! -------  线程间的通信:简单来说,就是多个线程在操作同一资源,但操作的动作不同. 试想一下,对于同一个资 ...

  5. java基础------多线程(转)

    24.01_多线程(多线程的引入)(了解) 1.什么是线程 线程是程序执行的一条路径, 一个进程中可以包含多条线程 多线程并发执行可以提高程序的效率, 可以同时完成多项工作 2.多线程的应用场景 红蜘 ...

  6. 10 Java基础 多线程2

    /* 线程间通讯: 其实就是多个线程在操作同一个资源 但是操作的动作不同 */ class Res { Stringname; Stringsex; } class Input implements ...

  7. java基础—多线程

    1.Thread类 package com.wjl.base;public class MyThread extends Thread {/*** 利用继承的特点* 将线程名称传递 * @param ...

  8. 黑马程序员——Java基础---多线程

    ------Java培训.Android培训.iOS培训..Net培训.期待与您交流! ------- 多线程 一.概述 说起多线程,我们就需要首先来谈谈什么叫做进程.所谓进程,就是在计算机上正在进行 ...

  9. Java基础---多线程宝典

    多线程 文章目录 多线程 核心概念 `Process`与`Thread` 线程三种创建方式 继承`Thread`类 使用多线程实现下载网络图片 实现`Runnable`接口 多线程同时操作同一个对象 ...

  10. 黑马程序员JAVA基础-多线程

    ------- android培训.java培训.期待与您交流! ---------- 线程: 线程是进程中的一个独立的控制单元 线程在控制着进程的执行 一个进程中至少有一个线程 线程的创建 第一种方 ...

最新文章

  1. INDEX FULL SCAN和INDEX FAST FULL SCAN的区别
  2. nginx:413 Request Entity Too Large 及 修改 PHP上传文件大小配置
  3. python的特点和优点-【Python面试】 Python 的特点和优点是什么?
  4. 【Android】将Xamarin For VS升级为4.0.1.145版
  5. 2019第十届蓝桥杯比赛总结(B组c/c++)
  6. ctf mysql hash传递_分享个 CTF 小工具 bruteHASH
  7. Thingsboard 3.1.0 - windows下安装、发送mqtt、仪表板显示
  8. BackTrack3(BT3破解wifi密码)
  9. R语言Kmeans聚类分析
  10. gtool:操作genotype data的利器
  11. HP1010和HP1020的区别
  12. dede所有目录模板全解
  13. div网页布局(做一个简单网页界面为例)
  14. 汽车HiL测试简单介绍及其优势
  15. 饿了么为啥给你推荐这个?本地生活搜索算法解密
  16. oracle数据库什么情况下创建索引比较好
  17. 时间触发以太网TTE
  18. 孟庆国:未来政府数字化转型——从“技术釆纳”到“价值赋能”
  19. SiO2/KH550修饰四氧化三铁纳米磁性颗粒|PDA包裹四氧化三铁磁性纳米颗粒(科研级)
  20. 20P60 PR模板预设10 VHS专业预设包制作旧镜头复古磁带效果含背景音乐

热门文章

  1. 高项、高级项目管理师论文-人力资源管理
  2. 【数据分析】⚠️走进数据分析 2⚠️ 爬虫简介
  3. 设置Centos7时区
  4. You tube music
  5. 英语知识系列:26个字母在单词中的发音总结
  6. WEB端工程环境安装
  7. 王家林人工智能AI第13课:使用Logistic Regression在Social Network上销售汽车并进行可视化性能评估老师微信13928463918
  8. cadence、PADS、protel教程(PCB Layout图文教程终结版)
  9. Dart中的构造函数
  10. 在excel中如何快速准确录入身份证号码?