文章目录
- 1. 可见性,有序性,原子性
- 2. java中并发和并行
- 3. 通常线程有哪几种使用方式?
1. 可见性,有序性,原子性
可见性(Visibility):
指一个线程修改了共享变量的值之后,其他线程能够立即看到这个修改后的值。Java 语言中通过 volatile 关键字实现可见性,使用 volatile 关键字声明的变量对所有线程都是可见的,修改一个 volatile 变量会立即更新到主存,读取 volatile 变量时会从主存中读取最新的值。
有序性(Ordering):
指指令在程序中执行的顺序。Java 语言中,由于指令重排的存在,指令在程序中执行的顺序不一定和程序中的顺序一致。Java 通过 synchronized、volatile 和 final 这些关键字来保证有序性。
- synchronized 关键字可以确保同一时刻只有一个线程执行临界区内的代码,从而保证临界区内的指令不会被重排。
- volatile 关键字可以禁止指令重排,保证代码执行的顺序和程序中的顺序一致。
- final 关键字可以确保变量的值只能被赋值一次,从而避免指令重排。
原子性(Atomicity):
指一个操作是不可中断的,要么全部执行完成,要么不执行。Java 语言中通过 synchronized 关键字和 java.util.concurrent.atomic 包下的原子类来实现原子性。
- synchronized 关键字可以确保同一时刻只有一个线程执行临界区内的代码,从而保证操作是原子的。
- java.util.concurrent.atomic 包下的原子类可以确保一些特定的操作是原子的,例如原子的读取和修改一个变量的值。
2. java中并发和并行
并发指的是在同一时间段内,有多个线程在执行不同的任务,但是这些任务可能会相互干扰或者依赖于其他线程的执行结果。在并发编程中,我们需要考虑如何协调各个线程的执行,避免竞态条件、死锁等问题。
并行指的是同时执行多个任务。在计算机中,多核处理器可以同时执行多个线程,从而实现并行。在并行编程中,我们需要考虑如何将任务分解为多个子任务,同时利用多个处理器执行这些子任务。
3. 通常线程有哪几种使用方式?
- 继承 Thread 类:通过继承 Thread 类,重写 run() 方法来定义线程的执行逻辑,然后创建线程对象并调用 start()
方法启动线程。 例如:
public class MyThread extends Thread {
@Override
public void run() {
// 线程执行逻辑
}
}
MyThread t = new MyThread();
t.start();
- 实现 Runnable 接口:通过实现 Runnable 接口,重写 run() 方法来定义线程的执行逻辑,然后创建 Thread 对象并传入 Runnable 实例,调用 start() 方法启动线程。
例如:
public class MyRunnable implements Runnable {
@Override
public void run() {
// 线程执行逻辑
}
}
MyRunnable r = new MyRunnable();
Thread t = new Thread(r);
t.start();
- 实现 Callable 接口:通过实现 Callable 接口,重写 call() 方法来定义线程的执行逻辑,并可以返回执行结果,然后创建 FutureTask 对象并传入 Callable 实例,调用 start() 方法启动线程。
例如:
public class MyCallable implements Callable<String> {
@Override
public String call() throws Exception {
// 线程执行逻辑
return "result";
}
}
MyCallable c = new MyCallable();
FutureTask<String> ft = new FutureTask<>(c);
Thread t = new Thread(ft);
t.start();