进程、线程、多线程

进程:
正在进行中的程序,一个程序的执行过程,需要资源:内存、cpu。
线程:
属于进程,指的是一个可以独立运行的代码片段(执行单元、执行路径)。
一个进程中有多个可以独立运行的执行单元,这样的进程称之为多线程的进程。
一个进程中至少有一个线程,这样的进程称之为叫做单线程的进程。
多线程的进程共享同一块内存空间。
CPU在执行时,某一时刻只能执行一个进程,做着高速的切换动作,导致看到的是貌似同时执行的效果(单核)。CPU执行线程的时间是不确定的。抢占式方式抢占CPU的调度。
同类的线程共享堆和方法区资源,但每个线程私有自己的程序计数器、虚拟机栈、本地方法栈。程序计数器私有是为了线程切换后能恢复到正确的位置。而虚拟机栈和本地方法栈私有是为了线程中的局部变量不被其他的线程访问到。

进程是相互独立的,但同一进程的线程可能会相互影响。

并行和并发:
并行:多个任务同时执行,在某一时刻每个任务都在执行,前提–多核。
并发:多个任务同时执行,在某一时刻只有一个任务在执行,其他任务在等待cpu。

创建线程:
java.lang包中有一个Thread对象,用于描述线程事物。
主线程:要运行的代码封装到main方法中的。
子线程:要运行的代码封装到run和call方法中。
方式1:继承方式
1.定义类继承Thread类
2.重写run方法
3.创建子线程对象
4.启动线程,调用start方法

在这里插入图片描述

方式2:实现接口
1.定义类实现Runnable接口
2.重写run方法
3.创建实现类对象
4.创建线程对象,并将实现类对象作为参数传递给线程对象的构造方法
5.调用strat方法。启动线程

在这里插入图片描述

方式3:实现接口Callable
1.定义类实现Callable接口
2.实现call方法
3.执行call方法会得到一个Future对象,可以调用get方法,获取线程执行的结果
4.创建Future的实现类对象,并将Callable的实现类对象作为参数传递给其构造方法
5.创建线程对象,并将Future的实现类对象传递给其构造方法
6.调用start方法,启动线程

在这里插入图片描述
三种方式区别:
1.继承方式从代码角度看最为简单。实际开发不建议使用。因为:继承Thread不能再去继承其他类(使用继承的前提是子类是父类的一种);线程对象和线程任务绑定在一起,提高了耦合度。调用start方法,内部调用start0方法,这个方法是本地方法,回调run方法,由于创建的是子类对象,子类中并将run方法重写了,因此运行子类的run中的内容。
2.实现Runnable接口,建议使用方式。可以去继承其他类,实现其他接口,在类中还可以定义其他功能和属性。实现类与线程对象是分离开的(线程对象和线程任务是分离开的)。创建Thread对象时,会将实现类对象赋值给Thread的成员变量target(target = new MyRun()),t.start–>start0–>run–>target != null .target.run().
3.实现Callable接口与实现Runnable接口方式类似的,有一些区别,线程任务方法即call方法,该方法带有返回值,并且允许在方法中抛出异常,获取返回值通过Future对象来操作,这个对象中还封装了一些其他的方法,如:判断线程是否执行完的状态,取消任务等。

常用方法:

1.获取当前线程对象的引用
static Thread currentThread()
2.获取线程名称
getName():主线程名称默认是main
子线程名称默认是:Thread-0 , Thread-1,…编号从0开始。
3.设置线程名称
setName(String name) 线程启动前设置和启动后设置都可以。

构造方法:
Thread(String name)

在这里插入图片描述

Thread(Runnable,String name)

在这里插入图片描述

4.设置和获取线程的优先级
每个线程都有一个优先级,优先级别高的线程。被cpu调度的可能性更大一些。
优先级别:1-10.每个线程创建时都有默认优先级,级别是5。
获取优先级:getPriority()
设置优先级:setPriority()
设置时找临界值,要么最大,要么最小。
最大优先级、最小优先级、默认优先级

在这里插入图片描述
在这里插入图片描述

6.守护线程
创建的线程都可以设置为守护线程(默认创建的线程都是非守护线程),守护线程也称为后台线程,为非守护线程提供服务的,因此非守护在,守护在,否则守护退出执行。
判断是否是守护线程: isDaemon()
设置线程是守护线程:setDaemon(true)(线程启动前设置)

在这里插入图片描述

7.让步方法:
static yield():使当前线程由运行态回到可运行态,意味着让其他线程先执行(优先级别高的线程先执行),但是优先级别高仅仅是被调度的可能性变大了,不能保证一定优先执行。有可能这个方法设置后和没设置效果相同。

8.中断线程
interrupt():某个线程正在休眠状态,如果想要打破这种状态,调用interrupt()。
9.休眠方法
static sleep(long millis):设置当前线程休眠时间millis时间
意味着主动放弃执行资格,时间到了恢复可行状态。
多线程运行时,某个线程有异常,对其他线程有影响?
没有影响,依旧能执行,只有出现异常的线程停止执行。

volatile关键字:
把变量声明为 volatile ,这就指示 JVM,这个变量是共享且不稳定的,每次使用它都到主存中进行读取。所以,volatile 关键字 除了防止 JVM 的指令重排 ,还有一个重要的作用就是保证变量的可见性。

并发编程的三个重要特征:
1、原子性:一次操作或者多次操作,要么所有的操作全部得到执行,不会因为受到任何因素的干扰而中断执行,要么都不执行,synchronized可以保证代码的原子性。
2、可见性:当一个线程对共享变量进行修改,另外的线程访问的是这个变量的最新值,volatile保证共享变量的可见性。
3、代码在执行的过程中的先后顺序,Java 在编译器以及运行期间的优化,代码的执行顺序未必就是编写代码时候的顺序,volatile防止指令重排。

synchronized和volatile的区别:它们是互补的存在不是对立的存在,volatile关键字只能对变量进行修饰,synchronized可以对代码块和方法使用。vlatile只能保证数据的可见性。不能保证数据的原子性,而synchronized都能保证。volatile保证的是变量在多个线程之间的可见性,synchronized保证的是多个线程访问资源的同步性。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值