Java中therad_java中Thread的深入了解(一)

线程

线程是进程中的一个单一顺序的执行单元,也被称为轻量进程(lightweight process)。线程有自己的必须资源,同时与其他线程进程共享全部资源。同一个进程中,线程是并发执行的。由于线程的之间的相互制约,线程有就绪、阻塞、运行、结束等状态。

一 新建线程

我们先创建两个线程类:

新建一个MyThread类 继承 Thread来覆盖 run方法:

a7f139599011

MyThread类

新建MyRunnable类 实现Runnable 接口:

a7f139599011

MyRunable类

创建以及执行两个线程类

a7f139599011

主线程Main

a7f139599011

线程结果

二 验证线程并发

在上述创建的MyThread类和MyRunnable类各自的run方法输出上 加个for循环for(int i=0;i<10000;i++);

a7f139599011

循环线程

a7f139599011

输出结果extends

如果是顺序执行,应该会是 extendsThread全部输出完 ,才输出implement thread。但是这并不是而是出现交叉结果 证明线程是并发执行。

交叉原理就是每个代码 在cpu时间片内执行一段时间,到时间就换一个代码 在cpu时间片内执行,但是如果时间片内打印完了,就看不见交叉现象。

a7f139599011

单核cpu

三 线程声明周期(或者线程状态)

java中线程基本上有以下图片中的几种状态:

a7f139599011

线程状态

首先我们要做一个输出线程状态的类:

线程状态public static void printThreadState(Thread thread){

Thread.State state=thread.getState();

switch(state){

//1.新建状态

caseNEW:

info(thread.getName()+" state is NEW");break;

//2.执行状态

case RUNNABLE:

info(thread.getName()+" state is RUNNABLE");break;

//3.等待超时状态

case TIMED_WAITING:

console.info(thread.getName()+" state is TIMED_WAITING");break;

//4.等待状态

case WAITING:

info(thread.getName()+" state is WAITING");break;

//5.阻塞状态

case BLOCKED:

info(thread.getName()+" state is BLOCKED");break;

//6.结束状态

caseTERMINATED:

info(thread.getName()+" state is TERMINATED");break;

default:

info

(thread.getName()+" state is UNKOWN");

}

}

//打印

public static  void info(Object o){

System.out.println(String.valueOf(o));

}

1.新建状态:

new之后 start之前都属于NEW状态,一旦状态变成其他,则不会再变成NEW状态。public static  void main(String args[]) throws InterruptedException{

Thread t=new Thread(new Runnable() {

@Override

public void run() {

}

});

printThreadState(t);//查看new之后的thread状态

}

2.执行状态

在run()方法里的时候,线程处于执行状态。一旦run()方法执行完毕,则状态就不是执行状态了

a7f139599011

执行状态

a7f139599011

线程状态输出结果

3.等待超时状态

当调用wait(long timeout)方法的时候,线程处于等待状态,并且超时后并不马上返回,而是等待获取锁后返回。

a7f139599011

查看wait(long timeout)

a7f139599011

输出结果

验证超时后并不马上返回,而是等待获取锁后返回。

a7f139599011

添加一条输出结果

a7f139599011

如果是wait(long timeout)方法时候,提前先把锁获取过来等待20s

a7f139599011

会发现输出结果线程还是阻塞状态

所以我们会发现一个问题,wait的超时只是一个预想, 多少时间后我再去获取锁,如果拿到就返回 拿不到就处于等待状态。这里就会发现这里等待是最少需要long timeout时间。

wait(等多少时间后 再去竞争锁),wait的时间内 我不去竞争 跟别人抢锁,所以这个时间 不保证锁一定能抢回来。

注意:Thread.sleep 也会进入TIME_WAITING状态。

5.等待状态

wait()睡眠不参与抢锁,等待notify来进行唤醒。

a7f139599011

放弃抢锁,处于waiting状态

a7f139599011

waiting状态时候唤醒

a7f139599011

输出结果

wait 也可以通过interrupt唤醒,interrupt是中断线程的方法。

5.阻塞状态

如果获取不到锁,就一直在阻塞状态,直到获取锁为止。

a7f139599011

把循环锁死,当状态位锁死的时候释放锁

a7f139599011

输出结果

6.结束状态

在run()方法执行结束以后,线程处于结束状态

a7f139599011

结束状态

但是当这个线程执行结束了之后,是否代表这个线程被销毁了呢。然而只是线程执行单元销毁了,但是线程对象还在。虽然这个线程对象还存在,但是它已经不能进行再次的start()方法进行执行了。

四 研究多线程锁问题

经典并发问题:当运行一万个线程想List插入的时候,预期结果是有10000个,但是输出确不是10000个,而是少于1000个。原因是 线程并发执行获取list的长度是过期的。

比如我拿到list ,你也拿到list ,咱俩同时看list里有1条数据 我把数据插入第二个位置 ,你也插入第二个位置 ,就会导致list最终结果只有2条数据,实际上插入了3条数据。public static void ThreadMuliteTest() throws InterruptedException {

final List list=new ArrayList();

for(int i=0;i<10000;i++){

new Thread(new Runnable() {

@Override

public void run() {

list.add(Thread.currentThread().getName());

}

}).start();

}

Thread.sleep(1000);

System.out.println(list.size());

}

a7f139599011

输出结果

这就是线程并发问题,并发问题有个解决办法 就是对线程进行枷锁让他排队,我拿到了 你就不能拿。

synchronized 代码段是java给线程的一个控制权,可以锁住一个资源,防止被其他人用。加锁之后线程就进入了 排队状态 ,只有一个线程能拿到list的权限 其他等待。

a7f139599011

还有一种操作 就是我得到资源后 ,可以释放一段时间给别人用 ,超时了 我在拿回来自己用。public static void ThreadGetWait() throws InterruptedException {

Object lock=new Object();

new Thread(new Runnable() {

@Override

public void run() {

synchronized (lock){

console.info("线程一:拿到锁");

try {

lock.wait(100);//释放100ms

} catch (InterruptedException e) {

e.printStackTrace();

}

console.info("线程一:锁又被我拿回来了");

try {

Thread.sleep(1000);//睡1s 锁不给别人

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

}).start();

Thread.sleep(10);//休眠10ms防止第二个线程拿到锁

new Thread(new Runnable() {

@Override

public void run() {

synchronized (lock){

console.info("线程二:拿到锁");

try {

Thread.sleep(2000);//拿到锁后我要休眠2s

} catch (InterruptedException e) {

e.printStackTrace();

}

console.info("线程二:锁又回来了?");

}

}

}).start();

}

a7f139599011

输出结果

因为线程1先运行 肯定拿到锁,线程一暂时释放。所以线程二紧接着拿到了锁,线程二休眠了2s 期间并没有释放锁,所以线程1一直处于阻塞状态,线程二执行完成后 释放锁 线程一 打印 最后一句。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值