java多线程

为什么需要多线程?

打开任务管理器,我们会看到计算机里面有一个个的进程,进程进一步的划分也就是线程了。我们运行java程序实际上就是运行了一个jvm进程,jvm默认会用主线程来执行main方法,另外jvm里面还有负责垃圾回收的其他工作线程等等,java语言做了多线程的支持,也就是说我们可以使用多线程实现多任务。
现代计算机的cpu多采用多核架构,为了充分利用性能以及让耗时操作(读写文件等等)更有效率,所以在特定场合(高并发)需要多线程操作。

线程的生命周期

在Java程序中,一个线程对象只能调用一次start()方法启动新线程,并在新线程中执行run()方法。一旦run()方法执行完毕,线程就结束了。因此,Java线程的状态有以下几种:
New:新创建的线程,尚未执行;
Runnable:运行中的线程,正在执行run()方法的Java代码;
Blocked:运行中的线程,因为某些操作被阻塞而挂起;
Waiting:运行中的线程,因为某些操作在等待中;
Timed Waiting:运行中的线程,因为执行sleep()方法正在计时等待;
Terminated:线程已终止,因为run()方法执行完毕。


image.png

线程安全问题

当多个线程同时运行时,线程的调度由操作系统决定,程序本身无法决定。因此,任何一个线程都有可能在任何指令处被操作系统暂停,然后在某个时间段后继续执行。

这个时候,有个单线程模型下不存在的问题就来了:如果多个线程同时读写共享变量,会出现数据不一致的问题。
多线程模型下,要保证逻辑正确,对共享变量进行读写时,必须保证一组指令以原子方式执行:即某一个线程执行时,其他线程必须等待。通常我们会通过加锁和解锁的方式来确保执行顺讯。

但是加锁的过程中如果出现使用不当的情况,就会出现死锁。

public void add(int m) {
    synchronized(lockA) { // 获得lockA的锁
        this.value += m;
        synchronized(lockB) { // 获得lockB的锁
            this.another += m;
        } // 释放lockB的锁
    } // 释放lockA的锁
}

public void dec(int m) {
    synchronized(lockB) { // 获得lockB的锁
        this.another -= m;
        synchronized(lockA) { // 获得lockA的锁
            this.value -= m;
        } // 释放lockA的锁
    } // 释放lockB的锁
}

如果两个线程去执行上面两个方法就会出现死锁。那么我们应该如何避免死锁呢?答案是:线程获取锁的顺序要一致。

线程池

Java语言虽然内置了多线程支持,启动一个新线程非常方便,但是,创建线程需要操作系统资源(线程资源,栈空间等),频繁创建和销毁大量线程需要消耗大量时间。
那么我们就可以把很多小任务让一组线程来执行,而不是一个任务对应一个新线程。这种能接收大量小任务并进行分发处理的就是线程池。

简单地说,线程池内部维护了若干个线程,没有任务的时候,这些线程都处于等待状态。如果有新任务,就分配一个空闲线程执行。如果所有线程都处于忙碌状态,新任务要么放入队列等待,要么增加一个新线程进行处理。

threadLocal

顾名思义,指的就是线程里面的储存空间,在当前线程能一直获取同一个实例。实际上,可以把ThreadLocal看成一个全局Map<Thread, Object>:每个线程获取ThreadLocal变量时,总是使用Thread自身作为key。

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 进程和线程 进程 所有运行中的任务通常对应一个进程,当一个程序进入内存运行时,即变成一个进程.进程是处于运行过程中...
    胜浩_ae28阅读 5,142评论 0 23
  • 进程和线程 进程 所有运行中的任务通常对应一个进程,当一个程序进入内存运行时,即变成一个进程.进程是处于运行过程中...
    小徐andorid阅读 2,844评论 3 53
  • Java 多线程 线程和进程的区别 线程和进程的本质:由CPU进行调度的并发式执行任务,多个任务被快速轮换执行,使...
    安安zoe阅读 2,220评论 1 18
  • 线程的基本操作 用new关键字创建一个线程对象,然后调用它的start()启动线程即可。 线程有个run()方法,...
    kaixingdeshui阅读 292评论 0 1
  • 1、概述 进程应用程序向操作系统申请计算机资源(文件句柄,内存等)的最小单位,而线程是进程中可独立执行的最小单位。...
    Zzz_Ahu_163阅读 1,165评论 0 1