Java并发编程基础知识

 

进程和线程的关系

 

 

程序计数器是一块内存区域,用来记录线程当前要执行的指令地址,栈资源中存储线程的局部变量,以及线程的调用栈帧。

堆是进程中最大的一块内存,堆是被进程中所有线程共享的,存放使用new操作创建的对象实例。

三种线程创建方式

1.继承Thread类并重写run方法

static class MyThread1 extends Thread {

@Override

public void run(){

System.out.println("extend-Thread:"+this.getName());

}

}

调用start()方法后,线程进入就绪状态,等待获取CPU资源后处于运行状态,一旦run方法执行完毕,线程处于终止状态。

好处:在run方法内获取当前线程直接用this就可以

坏处:Java不支持多继承,继承Thread类后无法继承其他类

2.实现Runnable接口的run方法

static class MyThread2 implements Runnable{

@Override

public void run(){

System.out.println("implements-Runnable:"+Thread.currentThread());

}

}

可以继承其他类,但是任务没有返回值

3.使用FutureTask方式

static class MyThread3 implements Callable<String>{

@Override

public String call() throws Exception{

System.out.println("implements-Callable:"+Thread.currentThread());

return "Callable接口";

}

}

在主线程中创建一个FutureTask对象,然后使用创建的FutureTask对象作为任务创建线程并启动它,最后通过futureTask.get()等待任务执行完毕返回结果。

public static void main(String[] args){

MyThread1 t1 = new MyThread1();

t1.start();

Thread t2 = new Thread(new MyThread2());

t2.start();

FutureTask<String> futureTask = new FutureTask<>(new MyThread3());

new Thread(futureTask).start();

try{

String res = futureTask.get();

System.out.println(res);

}catch(InterruptedException e){

e.printStackTrace();

}catch(ExecutionException e){

e.printStackTrace();

}

}

 

只有FutureTask方式可以拿到任务返回结果。

 

wait()方法将线程挂起,并将共享变量释放。

 

notify()方法只唤醒一个线程

notifyAll()方法唤醒变量的等待集合里面所有线程

 

sleep()方法让线程让出指定时间的执行权,但是锁还是持有不让出。

 

join()方法等待调用改方法的线程运行结束再继续

 

yield方法告诉线程调度器自己占有的时间片还没有使用完但是自己不想用了,可以进行下一轮吗进程调度。相当于虽然可以继续进行下去但是暂停当前进程到下次再轮询到改进程时再继续。

 

void interrupt()方法:中断线程

bollean isInterrupted()方法:检查当前线程是否被中断,是返回true,否返回false;

boolean interrupted()方法:检测当前线程是否被中断,是返回true,否返回false;

 

Java的线程分两种,daemon线程(守护线程)和user线程(用户线程)

mian函数所在线程就是一个用户线程

当最后一个非守护线程结束时JVM会正常退出

userThread.setDaemon(true)设置线程为守护线程

 

ThreadLocal实际上是为不同的线程创建线程内部的变量

同一个ThreadLocal变量在父线程中设置值后在子线程是获取不到的。

使用InheritableThreadLocal让子线程可访问父线程中设置的本地变量

 

并发是指同一个时间段内多个任务同时都在执行

并行是说在单位时间内多个任务同时在执行

 

线程的工作内存展示

 

Java中的synchronized关键字

synchronized块是Java提供的一种原子性内置锁,java中每个对象都可以把他当做一个同步锁来使用。内置锁是排他锁,当一个线程获取这个锁后,其他线程必须等待该线程释放锁后才能获取锁。

进入synchronized块的内存语义是把在synchronized块中使用到的变量从线程的工作内存中清除,这样在synchronized块内使用到该变量就不会送线程的工作内存中获取,而是直接从主内存中获取,退出synchronized块的内存语义是把在synchronized块内对共享变量的修改刷新到主内存。

synchronized关键字会引起线程上下文切换并带来线程调度开销。

 

Java中的volatile关键字

当一个变量被声明为volatile时,线程在写入变量时不会把值缓存在寄存器或者其他地方,而是会把值刷新回主内存。其他线程读取该共享变量时会从主内存重新获取最新值。

 

Java中的原子性操作

原子性操作是指执行一系列操作时,这些操作要么全部执行,要么全部不执行,不存在只执行一部分的情况。

使用synchronized关键字可以实现线程安全性,即内存可见性和原子性。

 

Java中的CAS操作

CAS即Compare and Swap,是JDK提供的非阻塞原子性操作,通过硬件保证比较-更新操作的原子性。

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值