多线程和高并发(一) Thread

系列文章目录

多线程和高并发(一) Thread
多线程和高并发(二) volatile关键字
多线程和高并发(三) Compare And Swap
多线程和高并发(四) 线程间通信
多线程和高并发(五) ThreadLocal & Lock
多线程和高并发(六) ReentrantLock
多线程和高并发(七) 线程池



进程

狭义上理解:是运行在电脑中的一个程序,一个进程包含多个线程,再操作系统中是以进程来分配虚拟存储空间,文件描述符等。

线程

是进程的一个执行单元,每个线程都有自己的线程栈,自己的寄存器环境,自己的线程本地存储。

主线程和子线程

JVM启动时候会创建一个线程执行main方法,所以main方法所在的线程是主线程,线程之间不独立,例如在主线程创建线程A,A即为主线程的子线程。

串行,并发,并行

三者传输速度为:串行 <= 并发 <= 并行

并发:是一个核心运行多个线程,看似一起运行,其实是切换运行不同线程

并行:是多个核心同时分别执行线程。

串行:是一个核心按顺序执行线程。

线程的创建与启动

创建:创建一个线程就是new一个Thread,其中Thread实现了Runable接口

启动:使用Thread静态方法start()启动线程

注意

执行start()不代表立马启动了线程,因为线程发放需要等JVM调配,

多线程运行结果与代码执行顺序或调用顺序无关 ,

线程启动后,会执行run方法。

线程常用方法

currentThread()方法

获取当前线程对象,是Thread的静态方法;

Thread.currentThread();

setName()/getName() 方法

设置/获取当前进程的线程名称。

isAlive()方法

实例方法,返回Boolean值,判断当前线程是否处于活动状态,线程关闭也需要一段时间。

sleep()方法

静态方法,让执行sleep的线程休眠指定毫秒数,线程转为TIMED_WAITING状态

getId()方法

获取当前线程的ID,如果线程结束,ID可能会被复用。

yield()线程让步方法

静态方法,使用此方法的线程,会主动放弃使用cpu资源,线程转为READY状态,直到再次有空闲CPU,自动转为RUNNING状态。

	@Override
	public void run() {
		long begin = System.currentTimeMillis();
		long sum = 0;
		for (int i = 1; i <= 1000000; i++) {
			sum += i;
            //线程让步, 放弃 CPU 执行权
			Thread.yield();
		}
		long end = System.currentTimeMillis();
		System.out.println("用时: " + (end - begin));
	}

isPriority()方法

设置线程执行优先级,优先级越高,可能优先执行,默认是5,取值范围1-10,10最高。

优先级具有继承性,子线程会继承父线程的优先级。

interrupt()方法

实例方法,中断线程方法,配合isinterrupted()方法使用;

public class SubThread2 extends Thread {
    @Override public void run() {
        super.run();
        for(int i = 1; i <= 10000; i++){
            //判断线程的中断标志,线程有 isInterrupted()方法,该 方法返回线程的中断标志 
            if ( this.isInterrupted() ){ 
                System.out.println("当前线程的中断标志为 true, 我要退出了");
                // break; //中断循环, run()方法体执行完毕, 子线程运行完毕 
                return; //直接结束当前 run()方法的执行 
            }
            System.out.println("sub thread --> " + i); 
        } 
    } 
}

setDaemon()守护线程方法

线程分为用户线程和守护线程;

参数值为true,设置线程为守护线程,如果没有用户线程,守护线程会自动销毁,GC就是一个守护线程。

多线程生命周期

线程生命周期可以通过线程实例方法的getState()方法获取,返回值是一个枚举;

NEW:新建状态,创建线程对象,执行start方法之前。

RUNNABLE:可运行状态,是一个复合状态

  • READY:start()方法之后,JVM线程调度分配之前,可以使用yield方法将RUNNING状态 转为READY状态
  • RUNNING:JVM线程调度分配后,READY转为RUNNING状态,该状态表示正在执行。

BLOCKED:阻塞状态,线程发起阻塞I/O操作,锁被其它线程占有,这个时候被操作系统挂起,处于阻塞状态不会占用CPU资源,当阻塞执行完成,会自动转为RUNNABLE状态,阻塞状态的线程,即使调用interrupt()方法也不会改变其状态。

WAITING:等待状态,执行了object.wait(),thread.join()等无时间限制的方法,线程会转为WAITING状态,WAITING状态执行了object.notify()方法,或者加入的线程执行完毕,当前线程会转为RUNNABLE状态,处于WAITING状态的线程不会被分配CPU资源且不持有锁。

TIMED_WAITING:有限时间等待状态,线程执行了有限等待时间方法,例如thread.sleep(500)方法,当前时间过去后线程会转为RUNNABLE状态。

TERMINATED:终止状态,线程执行完run方法,结束处于终止状态(这是java线程状态,操作系统可能会复用线程或者注销线程)。
网络图片

多线程编程的优势与存在的风险

多线程编程优势:

  1. 提高系统的吞吐量
  2. 提高响应速度
  3. 充分利用多核(Multicore)CPU资源

多线程编程风险和问题:

  1. 线程安全问题:可能会产生脏读,数据丢失
  2. 线程活性问题:程序自身缺陷或者资源稀缺,导致线程一直处于非RUNNABLE状态
    1. 死锁(Deadlock):类似鹬蚌相争
    2. 锁死(Lockout):类似钥匙毁坏了
    3. 活锁(Starvation):类似强者恒强,而弱者抢不到资源
  3. 上下文切换:处理器一个线程切换到另一个线程。
  4. 线程活性问题:程序自身缺陷或者资源稀缺,导致线程一直处于非RUNNABLE状态
    1. 死锁(Deadlock):类似鹬蚌相争
    2. 锁死(Lockout):类似钥匙毁坏了
    3. 活锁(Starvation):类似强者恒强,而弱者抢不到资源
  5. 上下文切换:处理器一个线程切换到另一个线程。
  6. 可靠性:可能因为一个线程导致JVM意外终止
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值