线程基本概念

24 篇文章 0 订阅

程序、进程、线程

        程序:为完成特定任务的一段特定代码

        进程:正在运行的程序,是操作系统进行资源分配的最小单位.

        线程:是进程内部的最小单元,是操作系统进行任务调度的最小单元,隶属于进程

:一个进程中可以包含多个进程,线程隶属于进程,一个进程至少包含一个线程(主线程)

创建线程

        集成Thread类

        实现Runnable接口

        区别:继承Thread类: 类不能继承其他类

                实现Runnable: 类还可以继承其他类

Thread中的构造方法

        Thread()   创建一个新的线程

        Thread(String name)   创建一个指定名称的线程

        Thread(Runnable target)   利用Runnable对象创建一个线程,启动时将执行该对象的run方法

        Thread(Runnable target, String name)   利用Runnable对象创建一个线程,并指定该线程的名称

Thread类中的方法

        start()   启动线程

        setName(String name)   设置线程的名称

        getName()   返回线程的名称

        setPriority(int newPriority)   设置线程的优先级

        getProiority()   返回线程的优先级

        join()   等待线程终止

        currentThread()   返回对当前正在执行的线程对象的引用

        sleep(millis)   让当前正在执行的线程休眠(暂停执行),休眠时间又millis(毫秒)指定

线程优先级

        优先级较高的线程有更多获得CPU的机会,反之亦然。优先级用整数表示,取值范围是1~10,一般情况下,线程的默认优先级都是5,但是也可以通过 setProiority 和 getProiority 方法来设置或返回优先级。

线程状态

        线程生命周期

        

        新建:当一个Thread类或其子类被声明并创建时,新生的线程对象处于新建状态

        就绪:处于新建状态的线程被start()后,将进入线程队列等待CPU时间片,此时它已具备运行的条件,只是没分配到CPU资源

        运行:当就绪的线程被调度并获得CPU资源时,便进入运行状态,run() 方法定义了线程的操作和功能

        阻塞:在某种特殊情况下,被人为挂起或执行输入输出操作时,让出CPU并临时终止自己的执行,进入阻塞状态

        死亡:线程完成了它的全部工作或线程被提前强制性的终止或出现异常导致结束

多线程

        多线程是指程序中包含多个执行对象,即在一个程序中可以同时运行多个不同的线程来执行不同的任务,也就是说允许单个程序创建多个并行执行的线程来完成各自的任务

        优点:提高程序的响应

                提高CPU利用率       

                改善程序结构,将复杂任务分为多个线程,独立运行

        缺点:线程越多,占用内存越多、

                多线程需要协调管理

                线程之间对共享资源的访问会相互影响

线程同步

并行与并发

        并行:指两个或者多个事件在同一时刻发生

        并发:指两个或多个事件在同一时间间隔发生

多线程同步

        多个线程同时读写同一份共享资源时,可能会引起冲突。所以引入线程"同步",即各线程间要有先来后到

同步就是排队+锁

        几个线程之间要排队,一个个对共享资源进行操作,而不是同时进行操作;

        为了保证数据在方法中被访问时的正确性,在访问时加入锁机制

       

确保一个时间点只有一个线程访问共享资源。可以给共享资源加一把锁,哪个线程获取了这把锁,才有权利访问该共享资源

        在Java代码中实现同步

                使用synchronized(同步锁)关键字同步方法或代码块

synchronized(同步锁){
    //需要被同步的代码;
}

 同步锁

        同步锁可以是任何对象,必须唯一,保证多个线程获得时同一个对象(用来充当锁标记)

        同步执行过程:第一个线程访问,锁定同步对象,执行其中代码

                                第二个线程访问,发现同步对象被锁定,无法访问

                                第一个线程访问完毕,解锁同步对象

                                第二个线程访问,发现同步对象没有锁,然后锁定并访问

        注:一个线程持有锁会导致其他所有需要此锁的线程挂起;在多线程竞争下加锁,释放锁会导致比较多的上下文切换和调度延时,引起性能问题。

Lock(锁)

        synchronized

                锁对象可以是任何对象,但是对于多个线程必须是同一个

                在对象中,有一个叫对象头的区域,在对象头中有一个标志位(锁状态)

                synchronized 修饰方法时,并没有显式的让我们添加锁标志对象

                在修饰静态方法时,锁标志对象默认this

                在修饰非静态方法时,锁标志对象时Class类的对象

                每个类被加载到内存中,都会为该类创建一个Class类的对象,用于封装类的信息。一个类即使创建多个对象,Class类的对象只有一个

        ReentrantLock

                ReentrantLock 类实现了Lock,它拥有与synchronized 相同的并发性和内存于一,在实现线程安全的控制中,比较常用的是ReentrantLock ,可以显式加锁、释放锁

        synchronized 和 ReentrantLock区别

                synchronized 是关键字,底层实现是以编译后的指令来实现

                                       是隐式锁  自动添加,自动释放(任务执行完,或者出现异常)

                                       修饰代码块和方法

                                       需要对象头中的锁标志记录锁的状态

                                       是非公平锁(等待锁的时候,不需要排队的,一旦所释放,谁抢到,谁执行)

                ReentrantLock 是类  依赖是代码控制

                                         是显式锁   手动添加  手动释放

                                         只能修饰代码块

                                         内部维护锁的状态标志

                                         可以实现公平锁,内部维护一个同步队列

线程死锁

        不同的线程分别占用对方需要的同步资源不放弃,都在等对方放弃自己需要的同步资源,就形成了线程的死锁。出现死锁后,不会出现异常,不会出现提示,只是所有的线程都处于阻塞状态,无法继续。

线程通信

        线程通信指的是福哦个线程通过相互牵制,相互调度,即线程间的相互作用

        设计三个方法:        

               wait  一旦执行此方法,当前线程就进入阻塞状态,并释放同步监视器

                notify 一旦 执行此方法,就会唤醒被wait 的一个线程。如果有多个线程被wait ,就唤醒优先级高的那个

               notifyAll 一旦执行此方法,就会唤醒所有被wait 的线程

        注:  wait() ,  notify()   ,notifyAll() 三个方法必须使用在代码块或同步方法中

新增创建线程方式

        实现 Callable 接口与使用 Runnabl 相比,Callable 功能更强大些。

                相比 run() 方法,可以有返回值

                方法可以抛出异常

                支持泛型的返回值

                需要借助 FutureTask 类,获取返回结果

// 接受任务
FutureTask<Integer> futureTask = new FutureTask(任务);
//创建线程
Thread t = new Thread(futureTask);
       t.start();
Integer val = futureTask.get();//获得线程call方法的返回值
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值