线程概念:
面试 #JinDRJ(什么是线程?)
- 进程:进程会获得操作系统给的资源和CPU调度。
- 线程:线程是独立获得CPU调度和操作系统资源分派的基本单位。
- 进程下包含了多个线程。
- 线程共享其所属进程的资源。
- 线程间相互竞争CPU调度,是CPU调度的最小单位。
- 进程间切换开销大,线程间切换开销小。
线程的状态:
线程间关系
并发:
多个线程在运行,但每个时刻只有一个线程运行。(⭐强调一起出发)并行:
物理意义上的同时执行。(⭐强调一起执行)同步:
意义:线程间共享资源,但部分资源一次最好是仅一个线程使用(如打印机打印),所以需要 同步,使得线程排队,而不混乱。
Java提供的方法:
synchronized(object1){ //阻塞需要加锁,锁的对象应该是括号里配置的 名为 object1 的实例对象
try {
object1.wait(); //阻塞了当前对象对象后面的线程
} catch(InterruptedException e) {
// //
}
}
synchronized(object1) {
object1.notify(); //将唤醒 一个 线程
}
synchronized(this) {
this.notifyAll(); //将唤醒 所有 线程参与竞争
}
创建一个线程
Java 提供了三种创建线程的方法:
- 通过实现
Runnable
接口; - 通过继承
Thread
类本身; -
实现
Runnable
接口来创建线程具体实现:
类
RunnableA
实现Runnable
接口;- 重写
run()
,这是接口的要求; new Thread(RunnableA,"threadName");
,创建线程;-
Runnable
实际代码:```java class RunnableDemo implements Runnable { private Thread t; //其实还是得依托Thread类来拉起线程 这里的实例中的start()函数需要,所以写在类内部 private String threadName;
RunnableDemo( String name) { //规定名字 threadName = name; }
@Override public void run() { for(int i = 4; i > 0; i—) {
System.out.println("Thread: " + threadName + ", " + i);
} }
public void start () { //本实例封装了new Thread(),且threadName在Main中创建本类时已传入 if (t == null) {
t = new Thread (this, threadName); //重要,
t.start ();
} } }
public class Main {
public static void main(String args[]) {
RunnableDemo R1 = new RunnableDemo( “Thread-1”);
R1.start();
RunnableDemo R2 = new RunnableDemo( “Thread-2”);
R2.start();
}
}
<a name="UQmKY"></a>
#### 继承`Thread`来创建线程
<a name="wmEef"></a>
##### 具体实现:
1. 类`ThreadA`继承`Thread`类;
1. 重写`run()`,实现核心代码;
1. `new Thread(threadA,"threadName");`实现线程的创建;
1. `thread.start();`实现线程的拉起。
<a name="YsUq3"></a>
##### `Thread`实际代码:
```java
class ThreadDemo extends Thread {
private Thread t;
private String threadName;
ThreadDemo( String name) {
threadName = name;
}
public void run() {
for(int i = 4; i > 0; i--) {
System.out.println("Thread: " + threadName + ", " + i);
}
}
public void start () { //封装了真正拉起线程的 thread.start()
if (t == null) {
t = new Thread (this, threadName);
t.start ();
}
}
}
public class Main {
public static void main(String args[]) {
ThreadDemo T1 = new ThreadDemo( "Thread-1");
T1.start();
ThreadDemo T2 = new ThreadDemo( "Thread-2");
T2.start();
}
}
使得主线程等待子线程的执行:
thread.join();
将使得主线程等待名为thread的子线程的执行完成,才继续执行。
所以,
- 如果多个子线程,一个
.start();
马上又.join();
,将使得程序退变为单线程。 - 子线程全都先
.start();
,之后再都.join();
,此时,子线程间将异步执行,但主线程等待join()
的全部子线程。实现
Callable
接口创建线程
三种创建线程方法的对比:
- 采用实现
Runnable
、Callable
接口的方式创建多线程时,线程类只是实现了Runnable
接口或Callable
接口,还可以继承其他类。 - 使用继承
Thread
类的方式创建多线程时,编写简单(因为最终都是使用new Thread(T,"threadName");
拉起线程的),如果需要访问当前线程,直接使用this
即可获得当前线程。
Java线程关键字:
volatile(adj.不稳定的)(wa_al-tou)
volatile
用法:
volatile
意义:
- 表示这个变量的修改将立即写入主存;
表示对这个变量的读取将直接从内存读取,而不是 CPU 寄存器。
synchronized(v.同步,使在时间上一致)(syn-k_rui-nized)
synchronized
用法:加锁 代码块:
synchronized(this) { //唤醒也必须加锁,加锁的对象应该是需要执行唤醒操作的对象
this.notify(); //将唤醒 一个 线程
}
加锁 整个函数:
public synchronized void test() {
for (int i = 0; i < 5; i++) {
System.out.println("线程名:"+Thread.currentThread().getName() + ":" + (count++));
}
}
synchronized
意义:字面意思:同步;
- 当一个线程在访问
synchronized
中的内容时,其他想访问 此内容 的线程将被阻塞; 对于普通方法,锁是当前实例对象(
this
),对于静态同步方法,锁是当前类的class对象。Java线程相关方法:
Thread.sleep(long millisec);
:-
object.wait();
: -
object.notify();
: -
object.notifyAll();
: 唤醒对象等待池所有线程参与竞争。
Thread.sleep(long millisec);
和object.wait();
的区别:
🐵 #面试 #JinXD
Thread.sleep(long millisec);
不释放对象锁,object.wait();
释放对象锁;object.wait();
要搭配object.notify();
或者object.notifyAll();
来唤醒。