- 进程与线程
- 进程
- 线程
- 进程与线程的区别
- 并行与并发
- 并发
- 并行
- 同步和异步
- Java创建线程
- 继承Thread类
- 实现Runnable接口
- 使用FuntureTash类配合Thread
- 使用线程池,后面会专门讲解
- 线程上下文切换
- Thread常见方法
- start 与 run
- 程序由指令和数据组成,但这些指令要运行,数据要读写,就必须将指令加载至 CPU,数据加载至内存。在指令运行过程中还需要用到磁盘、网络等设备。进程就是用来加载指令、管理内存、管理 IO 的
- 进程是系统分配资源的最小单元
- 一个进程可以有多个线程
- 线程是cpu调度的基本单位,线程之间共享进程资源
- 进程的独立的,而线程存在于进程内,是进程的一个子集
- 进程拥有共享的资源,供内部的线程共享
单核 cpu 下,线程实际还是 串行执行 的。 *** 作系统中有一个组件叫做任务调度器,将 cpu 的时间片(windows下时间片最小约为 15 毫秒)分给不同的程序使用,只是由于 cpu 在线程间(时间片很短的)切换非常快,人类感觉是同时运行的 。总结为一句话就是: 微观串行,宏观并行
一般将这种现场轮流使用CPU的做法叫做并发,concurrent
简单来说,并发就是一段时间内,我干完这个,再去干那个,相当于一段时间内一个人干多件事情。而并行就是在某一个时间,我同时干了多件事,比如说我一边洗脚一边打王者荣耀。在现在的多CPU处理器下,并发和并行一般是同时存在的
- 需要等待结果返回,才能继续运行就是同步
- 不需要等待结果返回,就能继续运行就是异步
Java创建线程 继承Thread类
同步
就相当于是 当客户端发送请求给服务端,在等待服务端响应的请求时,客户端不做其他的事情。当服务端做完了才返回到客户端。这样的话客户端需要一直等待。用户使用起来会有不友好。
异步
就是,当客户端发送给服务端请求时,在等待服务端响应的时候,客户端可以做其他的事情,这样节约了时间,提高了效率。
存在就有其道理 异步虽然好 但是有些问题是要用同步用来解决,比如有些东西我们需要的是拿到返回的数据再进行 *** 作的。这些是异步所无法解决的。
//继承Thread类,重写run方法
new Thread("A"){
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
}.start();
实现Runnable接口
//实现runnable接口
new Thread(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
},"B").start();
//lamba表达式简化
new Thread(()->{
System.out.println(Thread.currentThread().getName());
},"C").start();
使用FuntureTash类配合Thread
//使用FutureTash类
FutureTask<Integer> task=new FutureTask<>(new Callable<Integer>() {
@Override
public Integer call() throws Exception {
return 100;
}
});
new Thread(task,"D").start();
System.out.println(task.get());
使用线程池,后面会专门讲解
线程上下文切换
因为以下一些原因导致CPU不再执行当前线程,转而执行其他线程
- 线程的CPU时间片用完
- 垃圾回收,导致的STW
- 有更高优先级的线程需要运行
- 线程自己调用了 sleep、yield、wait、join、park、synchronized、lock 等方法
当上下文切换发生时, *** 作系统需要保存当前线程的状态,恢复执行线程的状态。Java中对应的概念为程序计数器,它的作用是记住下一条jvm指令的执行地址,是线程私有的。
频繁上下文切换会降低性能
我们尝试使用run或者start来开启线程
new Thread("A"){
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+" runing....");
}
}.run();
new Thread("B"){
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+" runing....");
}
}.start();
main runing....
B runing....
Process finished with exit code 0
上面发现:直接调用run只是调用类的一个普通方法,并没有开启多线程。只有调用了start方法才开启了多线程。
查看源码
这里调用run方法只是调用了Runnable接口里的方法
明天在写
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)