进程:os中并发(同时运行)的一个任务,一个cpu(只能执行一种运算)可以执行多个任务
cpu一次只能执行一种运算为什么还能执行多个任务呢?
cpu分时间片,宏观并行,微观串行(一个时间片可能是几毫秒,几微妙,因为时间片很短所以看起来是多个任务在执行)
操作系统负责调度时间片的分配
jvm相当于一个软件运行在os上,也就是他是系统的一个进程,所以虚拟机不能能有多进程,但是他有多线程的概念
线程:在一个进程中,并发的一个顺序执行流程(系统分配时间片给进程,同样进程也分时间片给线程,也是宏观并行,围观串行)
线程组成
1:cpu时间片(由操作系统负责分配)
2:data(线程运行起来要和数据打交道,数据应该有一个相应的村粗空间)
对于数据 的存储 堆:存储new部分,堆空间共享
栈:存储引用,及局部变量,栈空间独立 (假如我们开启了三个线程,他们会有各自的栈空间,但是他们的堆空间是公用一个的)
进程间堆栈都是独立的,这是进程和线程(轻量级的进程【线程间数据交换是很容易的但是进程中数据交互相对难】)一个很大的区别
3:代码(为每个线程编写代码)
package testMemory;
public class TestThread2{
public static void main(String[] args) {
Thread thread = new Thread();
thread.start();
}
}
我们的线程有五个状态:
新生状态,就绪状态,阻塞状态,运行状态,结束状态
我们新建一个thread属于新生状态,在调用start方法后,他知识启动了线程,没有真正运行,这时在等待系统分配时间片,得到时间片后系统调用run方法,进入运行状态,运行之后进入结束状态
package testMemory;
public class TestThread2{
public static void main(String[] args) {
new Thread(
new Runnable() {
@Override
public void run() {
System.out.println("aa");
}
}
).start();
new NThread().start();
}
}
class NThread extends Thread{
public void run(){
System.out.println("bb");
}
}
线程阻塞的几种情况
等待输入数据(从文件,数据库,手动输入数据),调用sleep,调用join(a,b两个线程一方调用join则另一方阻塞,直到前者程序执行完毕后者才执行)
模拟压栈弹栈:
package testMemory;
public class TestThread2{
public static void main(String[] args) {
//多线程访问临界资源会发生错误 t1,t2同时访问s资源
Stack s = new Stack();
Thread t1 = new PushThread(s);
Thread t2 = new PopThread(s);
t1.start();
t2.start();
}
}
class Stack{
private char[]data = {'A','B',' ',' ',' '};
private int index = 2;//记录数组中有效元素的个数
//入栈
public void push(char c){
System.out.println(c+" push");
data[index] = c;
index++;
}
//出栈
public void pop(){
index--;
System.out.println(data[index] +" pop");
data[index] = ' ';
}
public void print(){
for(char c : data){
System.out.print(c+" ");
}
System.out.println();
}
}
class PushThread extends Thread{
private Stack s;
public PushThread(Stack s){
this.s = s;
}
public void run(){
//加上同步锁
synchronized (s) {
s.push('C');
}
}
}
class PopThread extends Thread{
private Stack s;
public PopThread (Stack s){
this.s = s;
}
public void run(){
//加上同步锁
synchronized (s) {
s.pop();
}
}
}