深入理解并发编程系列-线程-成神之路

进程:程序执行后就会产生一个进程,程序运行的一个实例。

线程: 线程是进程内部的 。线程就是指令流,一条一条指令构成。

线程是jvm进行cpu调度的最小单位,而进程是jvm进行资源分配的最小单位。一个进程里可以有多个线程。

线程创建方式

1 直接用Thread创建

 Thread t1 = new Thread(){
    	@Override
     	public void run(){
            
            
        }
 };
t1.start();

2 用runnable创建

Runnable task  = new Runnable(){
	@Override
    public void run(){
        
    }
};
Thread t1 = new Thread(task);
t1.start();
    

3用FutureTask 配合Thread

FutureTask t = new FutureTask(new Callable<Integer>(){
	//任务代码
    	@Override
    	public Integer call(){
            return new Integer(1);  
        }
});

Thread t1 = new Thread(t);
t1.start();
t.get();

FutureTask 在创建时需要传一个实现Callable接口的参数。这个接口中有个call方法,就是我们需要写的执行代码

FutureTask类有一个get方法。能得到线程执行后返回结果。

4利用lambda表达式创建线程

Runnable r = ()->{
  //执行代码  
};
Thread t1 = new Thread(r);

lambda表达式适用函数式接口(接口中只有一个方法需要实现)

Thread类本身就实现了Runable接口,所以最后都是调用Thread类中的run方法。

线程上下文切换

当一个线程的cpu时间片被用完后需要保存这个线程的执行状态和数据。 然后恢复其他线程的执行状态和数据。执行其他线程。然后等待该线程再次获得cpu时间片时。恢复状态继续运行。就是线程上下文切换。上下文切换比较耗费性能。所以线程不是越多越好。

线程相关api

start() 和 run()

start开启一个线程执行。
run 如果直接掉用run方法则不会开启线程,只是普通的方法调用

sleep()

让线程从running进入timed_waiting状态。线程会放弃cpu

其他线程可以调用interrupt方法打断sleep中的线程,并不会改变其interrupt标记,被打断的线程会抛出interruptException异常

睡眠结束后的进程也得等待cpu分配给他才能执行。进入就绪状态。

可以防止while(true)空转沾满整个cpu。在循环中添加thread.sleep

yield()

主动让出cpu,进入就绪状态。但是可能还会抢到cpu ,具体要看cpu分给谁。

TimeUtil.Second.sleep()

也可以达到和Thead.sleep一样的效果,内部也是调用thread.sleep只不过进行了单位换算。

线程优先级

setpriority() 没什么特别用处。主要还是得看cpu分给谁

join()

用来等待执行的线程结束

在主线程中调用t1.join就是主线程等待t1线程运行结束。

t1.join(long n) 最多等待n毫秒。如果超时了,就不等待了,当前线程继续向下运行

interrupt()

线程都有一个打断标记,表示这个线程是否被打断过。可以调用Thread.isinterrupted()看看打断标记是true还是false

打断 sleep wait join 进行等待的线程,打断后不会改变其 打断标记

本质打断阻塞的线程。sleep wait join 都是阻塞状态。这三个方式进入的阻塞状态被打断后,会把打断标记变为假。

如果打断的是正常的线程或者是park的线程,是会改变其打断标记为true

打断标记变为真后,再想park线程是停不下来的。

locksupport.park()

如果想再次把打断标记设置为假,那么我们可以调用Thread.interrupted()这个方法会返回当前打断标记,并且把打断标记设置为假。

对于正常运行的线程,被打断后,打断标记会变为真。

守护线程

只要其他非守护线程全部运行结束。 那么无论守护线程是否运行结束都会强制结束。

t1.setDaemon(true)

垃圾回收器就是一种守护线程。

线程状态

初始状态。创建了线程对象。

可运行状态。就是就绪状态。可以运行,只要分配到cpu就运行

运行状态。正在运行,当cpu时间片用完,进入可运行状态,等待下一次cpu分配,会导致线程上下文切换。

阻塞状态。

终止状态。线程运行结束。

根据Thread.state中,将线程分为六种状态

new。线程刚刚被创建还没有调用start()。

Runnable。包含了上面五种状态的。可运行状态,运行状态,阻塞状态。在java里无法区分这三种状态,都是runnable

blocked waiting timedwaiting都是java层面对于阻塞状态的不同划分。

在java中阻塞状态有3种 blocked waiting time_waiting

sleep 会导致 timed_waiting 有时间的等待就是timedwaiting

join 导致 waiting 没有时间的等待就是waiting

如果是synchronized锁导致的是blockd 等待锁的就是blockd

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值