程序(program) 为完成特定任务、用某种语言编写的一组指令的集合。即指一段静态的代码,静态对象。
进程(process) 程序的一次执行过程,或是正在运行的一个程序。是一个动态的过程:有它自身的产生、存在和消亡的过程。生命周期 ,进程作为资源分配的单位,系统在运行时会为每个进程分配不同的内存区域。
线程(thread) 进程可进一步细化为线程,是一个程序内部的一条执行路径。
若一个进程同一时间并行执行多个线程,就是支持多线程的
线程作为调度和执行的单位,每个线程拥有独立的运行栈和程序计数器(pc),线程切换的开销小
一个进程中的多个线程共享相同的内存单元/内存地址空间它们从同一堆中分配对象,可以访问相同的变量和对象。这就使得线程间通信更简便、高效。但多个线程操作共享的系统资源可能就会带来安全的隐患。
并行:多个CPU同时执行多个任务。
并发:一个CPU(采用时间片)同时执行多个任务。
常用方法:
static void yield():线程让步
暂停当前正在执行的线程,把执行机会让给优先级相同或更高的线程
若队列中没有同优先级的线程,忽略此方法
join() :当某个程序执行流中调用其他线程的 join() 方法时,调用线程将被阻塞,直到 join() 方法加入的 join 线程执行完为止
线程类型:
守护线程和用户线程,用户线程就是我们自己调用的线程,比如main方法,守护线程比如gc线程,特点,守护线程会在用户线程调用结束的时候停止。
生命周期:
线程安全(锁):
AQS:AbstractQueuedSynchronizer,即队列同步器。它是构建锁或者其他同步组件的基础框架
单例懒汉线程安全模式:
public class ThreadTest {
private static ThreadTest single=null;
public ThreadTest() {
}
public static ThreadTest getThreadTest() {
if (single==null){
synchronized (ThreadTest.class){
if (single==null){
single=new ThreadTest();
}
}
}
return single;
}
死锁示例:
public class ThreadTest {
public static void main(String[] args) {
Object a1 = new Object();
Object a2 = new Object();
new Thread(()->{
synchronized (a1){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(a1+"线程1");
synchronized (a2){
System.out.println(a2+"线程1");
}
}
} ).start();
new Thread(new Runnable() {
@Override
public void run() {
synchronized (a2){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
System.out.println(a2+"线程2");
synchronized (a1){
System.out.println(a1+"线程2");
}
}
}
}).start();
}
}
Lock(锁)
Lock是显式锁(手动开启和关闭锁,别忘记关闭锁),synchronized是隐式锁,出了作用域自动释放
Lock只有代码块锁,synchronized有代码块锁和方法锁
使用Lock锁,JVM将花费较少的时间来调度线程,性能更好。并且具有更好的扩展性(提供更多的子类)
class A {
private final ReentrantLock lock= new ReentrantLock();
public void m() {
lock.lock();
try {
//保证线程安全的代码;
} finally {
lock.unlock();
}
}
}
线程同步常用方法:
wait():令当前线程挂起并放弃CPU、同步资源并等待,使别的线程可访问并修改共享资源,而当前线程排队等候其他线程调用notify()或notifyAll()方法唤醒,唤醒后等待重新获得对监视器的所有权后才能继续执行。
notify():唤醒正在排队等待同步资源的线程中优先级最高者结束等待
notifyAll ():唤醒正在排队等待资源的所有线程结束等待
这三个方法只有在synchronized方法或synchronized代码块中才能使用
voliate
voliate对变量的读写是线程安全的,但是变量的操作却不是线程安全的。例如多线程对某个变量做++
i++
线程创建
1;继承Thread
2,implements Runnable
1和2的区别:
避免了单继承的局限性
多个线程可以共享同一个接口实现类的对象,非常适合多个相同线程来处理同一份资源。
3,implements Callable
4,ThreadPool
public class ThreadTest {
public static void main( String[] args){
//Thread方式
Thread1 test = new Thread1();
test.start();
for (int i = 0; i < 100; i++) {
System.out.println(Thread.currentThread().getName()+i);
}
//Runable方式
Runable2 test2 = new Runable2();
final Thread thread = new Thread(test2);
Thread thread2 = new Thread(test2);
thread.start();
thread2.start();
//Callable方式
ThreadTest test3= new ThreadTest();
FutureTask<String> futureTask = new FutureTask<>(test3);
new Thread(futureTask).start();
String s = futureTask.get();
System.out.println(s);
//线程池创建线程
ExecutorService executorService = ThreadPoolExecutor.getExecutorService();
for (int i = 0; i < 5; i++) {
Future<String> submit = executorService.submit(new Callable<String>() {
@Override
public String call() throws Exception {
return Thread.currentThread().getName()+"hello";
}
});
System.out.println(submit.get());
}
}
}
//1;继承Thread
class Thread1 extends Thread {
@Override
public void run() {
for (int i = 0; i < 100;
i++){
System.out.println(Thread.currentThread().getName()+i);
}
}
}
//2,implements Runnable
class Runable2 implements Runnable{
public void run() {
for (int i = 0; i < 100;
i++){
System.out.println(Thread.currentThread().getName()+i);
}
}
}
//implements Callable
class ThreadTest implements Callable<String> {
@Override
public String call() throws Exception {
System.out.println(Thread.currentThread().getName() + "hello");
return "hello";
}
}
//线程池
class ThreadPoolExecutor {
private static ExecutorService executorService = Executors.newFixedThreadPool(2);
private ThreadPoolExecutor() {
}
public static ExecutorService getExecutorService() {
return executorService;
}
}
ExecutorService:真正的线程池接口。常见子类ThreadPoolExecutor void execute(Runnable command) :执行任务/命令,没有返回值,一般用来执行 Runnable
Future submit(Callable task):执行任务,有返回值,一般又来执行
Callable void shutdown() :关闭连接池
Executors:工具类、线程池的工厂类,用于创建并返回不同类型的线程池
Executors.newCachedThreadPool():创建一个可根据需要创建新线程的线程池
Executors.newFixedThreadPool(n); 创建一个可重用固定线程数的线程池
Executors.newSingleThreadExecutor() :创建一个只有一个线程的线程池
Executors.newScheduledThreadPool(n):创建一个线程池,它可安排在给定延迟后运行命令或者定期地执行。