Java并发 day01进程和线程 并行和并发 java线程
Posted halulu.me
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java并发 day01进程和线程 并行和并发 java线程相关的知识,希望对你有一定的参考价值。
进程和线程
进程
1、程序由指令和数据组成,但这些指令要运行,数据要读写,就必须将指令加载至CPU,数据加载至内存。在指令运行过程中还需要用到磁盘、网络等设备。进程就是用来加载指令、管理内存、管理 IO 的(管理资源)
2、当一个程序被运行,从磁盘加载这个程序的代码至内存,这时就开启了一个进程。
3、进程就可以视为程序的一个实例。大部分程序可以同时运行多个实例进程,也有的程序只能启动一个实例进程
线程
1、一个进程之内可以分为一到多个线程。 一个线程就是一个指令流,将指令流中的一条条指令以一定的顺序交给 CPU 执行
2、Java中,线程作为最小调度单位(CPU从线程获取指令),进程作为资源分配的最小单位(管理资源)。 在 windows 中进程是不活动的,只是作为线程的容器
3、线程是由一些列指令组成的。
二者对比
1、进程基本上相互独立的,而线程存在于进程内,是进程的一个子集
2、进程拥有共享的资源,如内存空间等,供其内部的线程共享
3、进程间通信较为复杂
同一台计算机的进程通信称为 IPC(Inter-process communication)
不同计算机之间的进程通信,需要通过网络,并遵守共同的协议,例如 HTTP
4、线程通信相对简单,因为它们共享进程内的内存,一个例子是多个线程可以访问同一个共享变量
5、线程更轻量,线程上下文切换成本一般上要比进程上下文切换低
并行和并发
并发
单核CPU,线程是串行执行的。操作系统中有一个组件叫做任务调度器,将CPU的时间片(windows下时间片最小约为15毫秒)分给不同的线程使用,只是由于CPU在线程间的切换非常快。(微观串行,宏观并行)
线程轮流使用CPU就是并发,concurrent。
并行
多核 cpu下,每个 核(core) 都可以调度运行线程,这时候线程可以是并行的,也可以是并发的。
两者对比
并发(concurrent)是同一时间应对(dealing with)多件事情的能力(单核)
并行(parallel)是同一时间动手做(doing)多件事情的能力(多核)
java线程
创建线程
创建线程–方法1 继承Thread类(重写run)
创建线程–方法2 实现Runnable接口(重写run)
创建线程–方法3 FutureTask实现Callable(间接实现Runable接口,有返回值)
FutureTask:
FutureTask<Integer> futureTask = new FutureTask(new Callable() {
@Override
public Object call() throws Exception {
return 100;
}
});
Thread t3 = new Thread(futureTask, "t3");
t3.start();
Integer i = futureTask.get();
System.out.println(i);
查看进程和线程
tasklist | findstr java
taskkill /F /PID 进程编号
ps -aux | grep 进程PID
kill -9 进程PID
jconsole 远程监控配置
-Djava.rmi.server.hostname=
ip地址
-Dcom.sun.management.jmxremote
-Dcom.sun.management.jmxremote.port=连接端口
-Dcom.sun.management.jmxremote.ssl=是否安全连接
-Dcom.sun.management.jmxremote.authenticate=是否认证
java类
线程运行原理
栈(stack)和栈帧(Frame)
每个线程启动后,虚拟机会为其分配一块栈内存
每个栈由多个栈帧组成,对应着每次方法调用时占用的内存
每个线程只能有一个活动栈帧,对应着当前正在执行的方法。
线程上下文切换(Thread Context Switch)
导致CPU不再执行当前线程,转而执行另一个线程的代码的原因:
1、线程的CPU时间片用完
2、垃圾回收(会暂停其他线程)
3、有优先级更高的线程
4、线程自己调用了sleep、yield、wait、join、synchronized等方法
当Context Switch发生时,需要有操作系统保存当前线程的状态,并恢复另一个线程的状态,java中对应的概念就是程序计数器,它的作用是记住吓一跳JVM指令的执行地址和,是线程私有的。
1、状态包括程序计数器、虚拟机栈中每个栈帧的信息,如局部变量、操作数栈、返回地址等
2、Context Switch 频繁发生会影响性能。
常见方法
start是开启线程
run是执行线程中的方法。
直接调用 run 是在主线程中执行了 run,没有启动新的线程
使用 start 是启动新的线程,通过新的线程间接执行 run 中的代码
join(long n)有时效的等待,如果超过时间,就不会再继续等待。
join的底层原理就是wait()
sinterrupted()判断是否被打断,不会清除标记
interrupted()判断是否被打断,会清除标记
对于正常运行的线程,打断线程并不能让线程停止,需要借助打断标记打断
park 线程, 不会清空打断状态,一般和interrupted()清除标记一起使用
LockSupport.park();
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread("t1"){
@Override
public void run() {
while (true){
if(Thread.currentThread().isInterrupted()){
log.debug("打断");
break;
}
}
}
};
t1.start();
t1.interrupt();
}
sleep
1、调用 sleep 会让当前线程从 Runnable 进入 Timed Waiting 状态(阻塞)
2、其它线程可以使用 interrupt 方法打断正在睡眠的线程,这时 sleep 方法会抛出 InterruptedException
3、睡眠结束后的线程未必会立刻得到执行
4、防止CPU占用100%
5、建议用 TimeUnit 的 sleep 代替 Thread 的 sleep 来获得更好的可读性
TimeUnit.SECONDS.sleep(1);
yield(让出)
1、调用 yield 会让当前线程从 Running 进入 Runnable 就绪状态,然后调度执行其它线程
2、具体的实现依赖于操作系统的任务调度器
守护线程
默认情况下,Java进程需要等待所有线程都运行结束,才会结束。有一种特殊的线程叫做守护线程,只要其它非守护线程运行结束了,即使守护线程的代码没有执行完,也会强制结束。
@Slf4j(topic = "c.test")
public class Thread4 {
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread("t1"){
@SneakyThrows
@Override
public void run() {
log.debug("start");
Thread.sleep(2000);
log.debug("end");
}
};
t1.setDaemon(true);
t1.start();
Thread.sleep(1000);
log.debug("main");
}
}
垃圾回收器线程就是一种守护线程
Tomcat 中的 Acceptor 和 Poller 线程都是守护线程,所以 Tomcat 接收到
shutdown 命令后,不会等待它们处理完当前请求
以上是关于Java并发 day01进程和线程 并行和并发 java线程的主要内容,如果未能解决你的问题,请参考以下文章