多线程

1、  程序、进程、线程的区别:

a)         程序是指为了完成特定的功能,用某种语言编写的一组指令的集合,指的是静态代码

b)         进程:一个正在执行的程序成为一个进程。

c)         线程:进程可以进一步划分为线程,是一个程序内部的一条执行路径。如果一个进程同一时间允许多个线程同时执行,那么这个进程就是支持多线程的。

d)         使用多线程的优点:

                         i.              增强应用程序的响应速度,改善用户体验 。

                       ii.              提高计算机CPU的利用率

                      iii.              改善程序结构,使得又长又复杂的进程分为多个线程独立运行便于理解和维护。

2、  线程的分类:

a)         在Java语言中线程分为两类:用户线程和守护线程

b)         他们在其他方面几乎是一样的,唯一不同就是判断JVM何时离开

c)         守护线程是用来服务用户线程的,在启动一个县城之前调用Thread.setDaemon(true),可以把一个用户线程转换为守护线程

d)         Java虚拟机中的垃圾回收就是一个守护线程

e)         如果JVM中的线程全部都是守护线程,当前的JVM就会退出。

3、  对线程的创建方法:

a)         一个类继承Thread类然后重写run()方法,并且把需要分线程实现的功能写在run()方法中,然后在主线程中通过start()方法启动该线程然后就自动执行run()方法了。

b)         一个类通过实现Runnable接口的方法创建多线程,在重写的run()方法中放入需要分线程实现的功能,然后再主线程中可以创建多个线程用来执行当前的功能(上边实现Runnable的对象)。

c)         实现callable接口的方法创建多线程

d)         使用线程池的方式创建多线程

4、  Thread类中常用的方法:

a)         start():启动线程并且执行当前线程的run()方法。

b)         Run():需要子线程指向的方法放在run()方法中,这个方法和普通的方法是一样的,单独执行这个方法并不会创建一个新的线程。

c)         currentThread():Thread类中的静态方法用于获取当前的线程

d)         getName():获取线程的名字

e)         setName():设置线程的名字

f)          yield():调用此方法的线程会释放 当前CPU的执行权,然后和其他线程一起在重写抢夺CPU的使用权,有可能会再一次抢到。

g)         join():在线程A中调用了线程B的此方法,表示当执行到此方法的时候,线程A会停止执行,直到线程B执行结束,线程A才会接着执行。

h)         isAlive():判断当前线程是否存活

i)           sleep():显示的让调用这个方法的线程睡眠指定的时间。

j)           线程通信方法:wait()、notify()、notifyAll()

k)         设置线程的优先级(高优先级的线程只是有更大的概率在某一时间相比较低优先级的线程更容易抢到CPU资源,但仅仅是更大概率):Java线程的优先级分为10个档次:1-10,可以使用setProprity()方法来设置某一线程的优先级。线程在创建的时候默认是继承于父类的优先级。

5、  线程的调度:

a)         线程的调度策略:

                         i.              时间片策略

                       ii.              抢占式策略:优先级高的线程更容易强到CPU资源

b)         Java中线程的调度方法:

                         i.              同优先级的线程组成先进先出的队列,使用时间片策略

                       ii.              高优先级的线程使用优先调度的抢占式策略。

6、  线程的生命周期:

a)         JDK中使用Thread.State枚举来表示线程的几种状态。

b)         一个线程的完整生命周期一般经历五个状态:

                         i.              新建:当一个Thread类被声明并创建之后,此时处于新建状态

                       ii.              就绪:处于新建状态的线程被start()之后,等待CPU分配资源之后就能执行的状态称之为就绪状态,此时的线程已经具备了运行所需要的全部资源。

                      iii.              运行:当就绪状态的线程获取到CPU资源之后就能 正常运行。该线程执行的操作和完成的功能全部定义在run()方法中。

                      iv.              阻塞:在某种特殊情况下,让出CPU资源并中止当前正在执行的线程,进入阻塞状态

                       v.              死亡:线程完成要执行的代码或者提前被强制中止。

7、  线程的安全问题

a)         为什么会产生线程安全问题:当一个线程在操作共享数据(多个线程共同操作的数据变量成为共享数据)的时候,当前的线程还没有执行完对共享数据的操作,其他的线程就参与进来,造成线程安全问题

b)         如何解决线程安全问题:必须让一个线程在操作共享数据完毕之后其他线程才能参与进来

c)         Java如何解决线程安全问题:通过线程的同步机制来解决线程安全问题。

                         i.              方式一:同步代码快

Synchronnized (同步监视器){

         操作共享数据的代码块

}

同步监视器:由任何一个类的对象来充当,作用就是保证哪个线程获取到这个同步监视器,哪个线程就能操作执行大括号中的操作共享数据的代码。要求所有的线程必须公共同一个同步监视器。

                       ii.              方式二:同步方法

将操作共享数据的方法使用关键字synchronized进行声明。这样就将一个方法声明为同步方法,当一个线程执行此方法的时候其他线程就会被阻塞。同步方法的锁就是当前对象,只是没有显示的指明锁是谁。

                      iii.              线程同步机制的弊端:在同一个时间只能有一个线程访问共享数据, 这样就会导致线程的执行效率会变低,但是相比较而言还是优点大于缺点。

d)         执行哪些操作会释放锁

                         i.              当前线程的同步方法、同步代码块执行结束

                       ii.              当前线程在同步方法或者同步代码块中出现了未处理的异常或者错误

                      iii.              当前线程在同步代码块或者同步方法中执行了线程对象的wait()方法,导致当前线程暂停,并且释放锁。

e)         线程死锁问题

                         i.              线程死锁的原因:不同线程分别占用其他线程资源不放弃,线程之间相互得不到满足并且都在等待对方释放资源,这样就会形成死锁。

                       ii.              死锁的特点:死锁出现后程序不会报异常,但是线程也不会自动停止,全部线程都处于阻塞状态,无法继续执行。

                      iii.              线程死锁的必要条件:互斥条件(一个资源同一时间只能被一个线程使用)、请求与保持条件(一个线程因为请求资源而阻塞时并不会放弃别的已经获取到的资源)、不剥夺条件(线程获得的资源在该线程执行完之前不会被强制剥夺)、循环等待条件(若干个线程之间形成相互循环等待资源的关系)。

f)          线程通信

                         i.              wait()、notify()、notyfyAll()这三个方法是在Object()类中定义的,但是这三个方法只能使用在同步代码块或者同步方法中,否则会出现异常。

                       ii.              这三个方法必须是放在Object类中的,因为这三个方法的使用必须是在同步代码块或者同步方法中,而且他们的调用者必须是同步监视器,而且任何一个类的对象都可以充当同步监视器,那么基于此这三个方法就必须放在Object类中。

g)         Lock锁

                         i.              Lock接口是控制多个资源对共享数据进行访问的工具,锁提供了对共享资源的单独访问,每次只能由一个线程对Lock对象加锁,每次访问共享数据之前都要先获取锁。

                       ii.              JUC包中的 Lock 接口支持那些语义不同(重入、公平等)的锁规则。所谓语义不同,是指锁可是有"公平机制的锁"、"非公平机制的锁"、"可重入的锁"等等。"公平机制"是指"不同线程获取锁的机制是公平的",而"非公平机制"则是指"不同线程获取锁的机制是非公平的","可重入的锁"是指同一个锁能够被一个线程多次获取。

                      iii.              ReentrantLock是Lock的一个实现类,它拥有和sychronized一样的并发行和内存语义,在实现线程安全的过程中一般使用这个实现类进行显示加锁和显示释放锁。

                      iv.              为了避免线程出现死锁的情况,要求Lock的释放锁的代码必须放在finally代码块中,那么响应的操作共享数据的代码就必须放在try大括号内。

                       v.              Synchronized和Lock的异同点:

l  二者都是解决线程安全问题的方法

l   Synchronized机制在执行完同步代码之后会自动的释放同步监视器,但是Lock需要手动的启动和释放;

l  Lock是显示锁(手动启动和手动的释放),但是synchronized是隐式锁,出了作用域之后这个锁就自动释放了。

l  Lock只能对代码块上锁,但是synchronized有同步代码块和同步方法之分

l  Lock保证线程安全方面虽然和synchronized是一样的,但是JVM将花费较少的时间来调度线程,性能更好,效率较高,并且具有良好的扩展性。

                      vi.              wait()方法和sleep()方法的比较

l  相同点:一旦调用这两个方法都会使当前线程进入阻塞状态

l  两者声明的位置不一样;sleep方法是在Thread类中声明的,但是wait方法是在Object类中定义的

l  调用的要求不一样:sleep在任何地方都可以使用,但是wait方法就必须在同步代码块或者同步方法中使用

l  关于是否释放同步监视器的问题:如果两者都用在同步代码块中,那么sleep只会让当前线程阻塞,但不会释放当前线程握的锁,但wait则不是,使线程阻塞并且还释放锁。

8、  线程的创建方式三

a)         实现callable接口创建线程

b)         与runnable接口相比较,callable接口的功能更加强大

                         i.              有返回值

                       ii.              可以抛异常

                      iii.              支持泛型的返回值

                      iv.              需要借助FutureTask类,来获取返回值结果等。

c)         Future接口

                         i.              可以对Runnable、Callable任务的执行结果进行取消、查询是否完成、获取执行结果等操作

                       ii.              FutrueTask是Future接口的唯一实现类

                      iii.              FutrueTask同时又实现了Runnable、Callable接口,它即可以作为Runnable被线程执行,又可以作为Future获取Callable的返回值。

9、  使用线程池创建线程

a)         使用线程池的好处:提高程序的响应速度,降低系统资源的消耗,便于线程管理

b)         现在开发都是使用框架,创建线程都是使用线程池的方法进行创建,因为线程池中的一些主要属性是可以设定的,这样就能很方便的管理线程池。

转载于:https://www.cnblogs.com/BaoZiY/p/11376365.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值