java 线程栈空间_java进程/线程;堆和栈;多线程

本文详细介绍了Java中的进程和线程概念,堆和栈内存的区别,以及线程的生命周期。通过示例展示了如何创建多线程,并探讨了线程同步的重要性。同时,提到了线程同步的两种方法:synchronized和wait/notify机制。
摘要由CSDN通过智能技术生成

一.进程和线程

进程:在内存中运行的应用程序,一个exe是一个进程。

如:ps -exf  可以查看各个应用的进程,其中ppid为父进程;

ps aux | egrep '(cron|syslog)'      找出与 cron 与 syslog 这两个服务有关的 PID 号码  ;

kill -9 进程id 可以关闭该进程

线程:进程中的一个执行流程,共享同一个进程的内存。

二.堆与栈

堆内存:存放new出来的对象和数组,分出的内存由jvm的自动垃圾回收器进行管理。

栈内存:定义一个变量,取值等于new出来的对象和数组的首地址,即取一个变量名,实际的值存在堆内存中,地址放在定义的变量中,该变量被称为数组或对象的引用变量

(堆保存实际数据,为属性内容,栈保存数值的空间地址,为对象名称)

例如:int[] a=new int a[10]  为堆内存分配一段连续的内存空间

a[2]=4   引用变量相当于给数组起个名字,以后可以引用

内存分配:

1.类变量(static修饰):在堆中分配,堆中的内存地址存放在栈中,方便高速访问

2.实例变量:如   a[2]=4  ,作为堆对象的引用变量,引用完,被GC(garbage collection)垃圾回收器列入可回收的名单,但是不马上释放堆内存

3.局部变量:一般为for循环内定义,执行时在栈中开辟内存,脱离作用域后,内存释放,所以for内的变量一般定义在for内,而不是for外,防止占用内存

三.线程与内存

Thread类实例是一个对象,有变量和方法,生死于堆上

每个线程实例有一个调用栈,每创建一个线程,就产生一个调用栈,记录函数执行顺序,开独立栈是为了并行运行

线程分类:1.用户进程 (main为主线程,其他线程为用户进程)

2.守护进程:程序运行时在后台提供一种通用服务的线程,如:垃圾回收线程,内存管理线程,数据库连接池监控线程

非守护线程结束,则守护线程没有存在的必要,此时jvm退出,守护线程也关闭!!

784faa33868de24eca205b1049a9642b.png

四.线程的生命周期

线程生命周期的五种状态:

1346902967_1252.png

(1)新建(new Thread)当创建Thread类的一个实例(对象)时,此线程进入新建状态(未被启动)。

例如:Thread  t1=new Thread();

(2)就绪(runnable)线程已经被启动,正在等待被分配给CPU时间片,也就是说此时线程正在就绪队列中排队等候得到CPU资源。例如:t1.start();

(3)运行(running)线程获得CPU资源正在执行任务(run()方法),此时除非此线程自动放弃CPU资源或者有优先级更高的线程进入,线程将一直运行到结束。

当发生如下情况是,线程会从运行状态变为阻塞状态:

①、线程调用sleep方法主动放弃所占用的系统资源

②、线程调用一个阻塞式IO方法,在该方法返回之前,该线程被阻塞

③、线程试图获得一个同步监视器,但更改同步监视器正被其他线程所持有

④、线程在等待某个通知(notify)

⑤、程序调用了线程的suspend方法将线程挂起。不过该方法容易导致死锁,所以程序应该尽量避免使用该方法。

(4)死亡(dead)

当线程执行完毕或被其它线程杀死,线程就进入死亡状态,这时线程不可能再进入就绪状态等待执行。

自然终止:正常运行run()方法后终止

异常终止:调用stop()方法让一个线程终止运行

(5)堵塞(blocked)

由于某种原因导致正在运行的线程让出CPU并暂停自己的执行,即进入堵塞状态。

正在睡眠:用sleep(long t) 方法可使线程进入睡眠方式。一个睡眠着的线程在指定的时间过去可进入就绪状态。

正在等待:调用wait()方法。(调用motify()方法回到就绪状态)

被另一个线程所阻塞:调用suspend()方法。(调用resume()方法恢复)

五.如何创建多线程

多线程实现方式有2种:

(1)继承Thread类(单继承),并重写run方法

(2)实现Runnable接口(当创建的类继承了其他类时)

ps:为什么要单继承,多接口?--》防止继承的多个类中有相同的方法,不易区分,而接口没有方法体(多为抽象方法),可以多继承

先来编写一个单线程:

public classMythread {

@SuppressWarnings("static-access")public static voidmain(String[] args) {

Thread t=Thread.currentThread();

t.setName("单例线程");

System.out.println(t.getName()+" 正在运行");for(int i=0;i<5;i++){

System.out.println("线程正在休眠:"+i);try{

t.sleep(500);

}catch(InterruptedException e) {

System.out.println("线程出现错误了!!");

}

}

}}

运行结果:

单例线程 正在运行

线程正在休眠:0线程正在休眠:1线程正在休眠:2线程正在休眠:3线程正在休眠:4

编写一个多线程,使用第一种方法:

packagethread;public class Mythread3 extendsThread {

privateString name;private intms;//封装线程名和时间

/*使用类方法,直接赋值类中的类方法,在该类被加载到内存时,就分配了相应的入口地址。

从而类方法不仅可以被类创建的任何对象调用执行,也可以直接通过类名调用。类方法的入口地址直到程序退出才被取消。

类方法在类的字节码加载到内存时就分配了入口地址,因此,Java语言允许通过类名直接调用类方法,而实例方法不能通过类名调用。*/

public Mythread3(String name, intms) {this.name =name;this.ms =ms;

}//每个线程start()后进行run()

@Overridepublic voidrun() {//TODO Auto-generated method stub

try{

sleep(ms);

}catch(InterruptedException e) {//TODO: handle exception

System.out.println("线程出错啦");

}

System.out.println(name+"开始休眠"+ms);

}public static voidmain(String[] args) {//TODO Auto-generated method stub

Thread t1=new Mythread3("线程1",100);

Thread t2=new Mythread3("线程2",300);

Thread t3=new Mythread3("线程3",200);

t1.start();

t2.start();

t3.start();

}

}

运行结果:

线程1开始休眠100

线程3开始休眠200

线程2开始休眠300

使用第二种方法:

packagethread;class MyThread extendsThread{public int x = 0;public voidrun(){

System.out.println(++x);

}

}class R implementsRunnable{private int x = 0;public voidrun(){

System.out.println(++x);

}

}public classTest{public static voidmain(String[] args){try{for(int i=0;i<10;i++){

Thread t= new MyThread(); //Mythread类继承thread,使用方法(1),打印十次1

t.start();

}

Thread.sleep(10000);//让上面的线程运行完成

/*R类使用接口runnable,使用方法(2),10个线程对象产生的10个线程运行时打印了1到10。

10个线程称为同一实例(Runnable实例)的多个线程。*/R r= newR();for(int i=0;i<10;i++){

Thread t1= newThread(r);

t1.start();

}

}catch(Exception e) {//TODO: handle exception

}

}

}

运行结果:

六.线程同步

临界资源:多个线程共享的数据

java对象默认可以被多个线程共用,当用sychronized修饰时,则启动“互斥锁”机制,任一时刻只能由一个线程访问,即使该线程阻塞。

线程同步的方法有两种:

(1)synchronized(互斥锁)

(2)wait与notify

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值