❝
大家好呀,我是小羊,如果大家喜欢我的文章的话😁,就关注我一起学习进步吧~
❞
1.什么是线程
线程(Thread):轻量级进程,是操作系统进行调度的最小单位。一个线程是一个任务(一个程序段)的一次执行过程。线程不占有内存空间,它包括在进程的内存空间中。在同一个进程内,多个线程共享进程的资源。一个进程至少有一个线程。
线程有5种状态分别是:
-
创建状态 -
就绪状态 -
运行状态 -
阻塞状态 -
终止状态
操作系统创建线程时,线程处于创建态,CPU调度线程时,线程处于运行态,此时其它已创建的或者时间片到的线程就处于就绪态,当然还有些线程在进行磁盘、网络等IO时就处于阻塞态,操作系统销毁线程时,线程就处于终止态。另外,线程还具有静止就绪态和静止阻塞态,处于这两种状态,说明这个线程被操作系统挂起了,操作系统挂起线程,是为了观察和分析线程状态。

2.线程和进程的区别
-
从属关系不同: 从属关系不同:进程是正在运行程序的实例,进程中包含了线程,而线程中不能包含进程。 -
描述侧重点不同: 描述侧重点不同:进程是操作系统分配资源的基本单位,而线程是操作系统调度的基本单位。 -
共享资源不同:: 共享资源不同:多个进程间不能共享资源,每个进程有自己的堆、栈、虚存空间(页表)、文件描述符等信息,而线程可以共享进程资源文件(堆和方法区)。 -
上下文切换速度不同: 上下文切换速度不同:线程上下文切换速度很快(上下文切换指的是从一个线程切换到另一个线程),而进程的上下文切换的速度比较慢。 -
操纵者不同: 操纵者不同:一般情况下进程的操纵者是操作系统,而线程的操纵者是编程人员。
3.怎么创建一个线程
-
继承Thread类创建

-
通过Runnable接口创建线程类

-
使用Callable和Future创建线程

-
通过线程池创建
4.Thread 类中的start() 和 run() 方法有什么区别?
start()方法被用来启动新创建的线程,而且start()内部 调用了run()方法,这和直接调用run()方法的效果不一样。当你调用run()方法的时候,只会是在原来的线程中调用,没有新的线程启 动,start()方法才会启动新线程。
5.Java中Runnable和Callable有什么不同?
Runnable和Callable都代表那些要在不同的线程中执行的任务。Runnable从JDK1.0开始就有了,Callable是在 JDK1.5增加的。它们的主要区别是Callable的 call() 方法可以返回值和抛出异常,而Runnable的run()方法没有这些功能。Callable可以返回装载有计算结果的Future对象。
6.什么是线程安全?
如果每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期是一样的,这就是线程安全。反之,线程不安全
7.java 怎么保证线程安全
-
使用局部变量或者定义为final类型 -
上锁 Lock -
同步代码块 Synchonized -
使用ThreadLocal -
使用juc并发包下面的一些线程安全类
8.Java中notify 和 notifyAll有什么区别?
notify()方法不能唤醒某个具体的线程,所以只有一个线程在等 待的时候它才有用武之地。而notifyAll()唤醒所有线程并允许他们争夺锁确保了至少有一个线程能继续运行。
9.Sleep 和 wait 的区别
Java程序中wait 和 sleep都会造成某种形式的暂停,它们可以满足不同的需要。wait()方法用于线程间通信,如果等待条件为真且其它线程被唤醒时它会释放锁,而 sleep()方法仅仅释放CPU资源或者让当前线程停止执行一段时间,但不会释放锁。
10.Thread类中的yield方法有什么作用?
Yield方法可以暂停当前正在执行的线程对象,让其它有相同优先级的线程执行。它是一个静态方法而且只保证当前线程放弃CPU占用而不能保证使其它线程一定能占用CPU,执行yield()的线程有可能在进入到暂停状态后马上又被执行。
11.有三个线程T1,T2,T3,怎么确保它们按顺序执行?
你可以用线程类的join()方法在一个线程中启动另一个线程,另外一个线程完成该线程继续执行。为了确保三个线程的顺序你应该先启动最后一个(T3调用T2,T2调用T1),这样T1就会先完成而T3最后完成。
12.Java中synchronized 和 Lock 有什么不同?
-
synchronized 是同步代码块,使用较简单,不怎么灵活,JVM采用monitorenter、monitorexit两个指令来实现同步,monitorenter可以看作加锁,monitorexit看作释放锁。 -
lock:需要显示指定起始位置和终止位置。一般使用ReentrantLock类做为锁,多个线程中必须要使用一个ReentrantLock类做为对象才能保证锁的生效。且在加锁和解锁处需要通过lock()和unlock()显示指出。所以一般会在finally块中写unlock()以防死锁。
13.怎么检测一个线程是否拥有锁?
在java.lang.Thread中有一个方法叫holdsLock(),它返回true如果当且仅当当前线程拥有某个具体对象的锁。
14.volatile 是什么意思?
关键字,主要作用
1)保证可见性 2)不保证原子性 3)禁止指令重排
15.volatile 变量和 atomic 变量有什么不同?
volatile 变量和 atomic 变量看起来很像,但功能却不一样。Volatile变量可以确保先行关系,即写操作会发生在后续的读操作之前, 但它并不能保证原子性。例如用volatile修饰count变量那么 count++ 操作就不是原子性的。而AtomicInteger类提供的atomic方法可以让这种操作具有原子性如getAndIncrement()方法会原子性 的进行增量操作把当前值加一,其它数据类型和引用变量也可以进行相似操作。
今天的分享就先到这里啦。
喜欢我的话,可以给我点个赞呀。

原文始发于微信公众号(小羊架构):这些多线程的问题你会吗?
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/259868.html