java语言高级部分(多线程)

多线程

基本概念:程序、进程、线程。

(1)程序:是为了完成特定任务、用某种语言编写的一组指令的集合。即指一段静态的代码。静态对象。
(2)进程:是程序的一次执行过程,或是正在运行的一个程序。
(3)线程:进程可以进一步细化为线程,是一个程序内部的一条执行路径。

线程的创建和使用

方式一:继承Thread类
(1)创建一个继承于Thread类的子类。
(2)在子类中重写Thread中的run()方法。
(将此线程要执行的操作声明在run中)
(3)创建Thread子类对象。
(4)通过此对象调用start()方法。
start()方法:①启动当前线程。②调用当前线程的run()方法。
(5)问题:
①我们不能使用直接调用run()方法的方式启动线程。
②如果想再执行一个线程,不可以还让已经start()的线程再去执行,会报IllegalThreadStateException错误,我们要再新建一个线程。
(6)Thread类中常用的方法:
①void start():启动线程,并执行对象中的run()方法。
②run():线程在被调度执行时的操作。(通常需要重写)
③getName():返回当前线程的名称。
④setName(String name):设置当前线程的名称。
⑤currentThread():静态方法,返回当前执行代码的线程。
⑥yield():线程让步,释放当前cpu的执行权。
⑦join():在线程a中调用线程b的join()方法,此时线程a进入阻塞状态,直到线程b完全执行完以后,线程a才结束阻塞状态。
⑧sleep(long mills):让当前线程“睡眠”执行执行的时间。在指定的时间内,该线程是阻塞的。
⑨stop():强制结束线程的生命周期,不推荐使用,已过期。
⑩isAlive():返回boolean,判断线程是否存活。
(7)线程的优先级:
三种优先级:
① MAX_PRIORITY = 10;
② MIN_PRIORITY = 1;
③ NORM_PRIORITY = 5;//默认的优先级
如何获取和设置当前线程的优先级:
getPriority();//获取线程的优先级
setPriority();//设置线程的优先级

==说明:==高优先级的线程要抢占低优先级线程的cpu执行权。但是只是从概率上讲的,高优先级的线程高概率的情况下会被执行。并不意味着只有当高优先级的线程执行完以后,低优先级的线程才执行。

方式二:实现Runnable接口
(1)创建一个类实现了Runnable接口。
(2)在这个类中实现Runnable接口中的run()方法。
(3)创建该类的对象。
(4)创建一个Thread的对象,并将上边的这个对象传入Thread的构造器中。
(5)调用Thread对象的start()方法。

比较以上两种创建线程的方式
(1)开发中优先选择实现Runnable接口的方式。
原因:
①实现Runnable的方式没有单继承的局限性。
②对于操作共享数据的情况,实现Runnable接口的方式更适合。
(2)联系:Thread类实现了Runnable接口。
(3)相同点:两种方法都要重写run()方法,将线程要执行的操作写在run()方法中。

方式三:实现Callable接口
(1)实现Callable接口:
①创建实现Callable接口的类。
②实现Callable接口中的call()方法,将此线程要执行的操作声明在call()方法中。
③创建Callable实现类的对象。
④将此Callable实现类的对象作为参数传递到FutureTest类的构造器中,并创建FuturTest的对象。
⑤将FutuerTest这个对象作为参数传递到Thread类中的构造器中,创建Thread对象。
⑥创建Thread对象的start()方法。
⑦如果想要获取返回值,调用FutureTest对象的get()方法。
(2)如何理解实现Callable接口的方式创建多线程比实现Runnable接口方式创建多线程更方便。
①call()方法有返回值。
②call()方法可以抛出异常,被外面的操作捕获,获取异常信息。
③Callable支持泛型。

方式三:使用线程池
(1)背景:经常创建和销毁、使用量特别大的资源,比如并发情况下的线程,对性能的影响很大。
(2)思路:提前创建多个线程,放入线程池中,使用时直接获取,使用完放回池中。可以避免频繁创建销毁、实现重复利用。类似生活中的公共交通工具。
(3)好处:
①提高响应速度(减少了创建心线程的时间)
②降低资源消耗(重复利用线程池中的线程,不需要每次都创建)
③便于县城管理。
(5)顺序:
①提供指定执行线程数量的线程池。
②执行指定的线程池的操作。需要我们提供Runnable接口或Callable接口实现类的对象。
③关闭线程池。

线程的生命周期

(1)新建:当一个Thread类或其子类的对象被声明并创建时,新生的线程对象处于新建状态。
(2)就绪:处于新建状态的线程被start()后,将进入县城队列等待cpu时间片,此时他已经具备了运行的条件,只是没分配到cpu资源。
(3)运行:当就绪的线程被调度并获得cpu资源时,便进入运行状态,run()方法定义了线程的操作和功能。
(4)阻塞:在某种特殊情况下,被认为的挂起或执行输入输出操作时,让出cpu并临时种植自己的执行,进入阻塞状态。
(5)死亡:线程完成了它的全部工作或线程被提前强制性中止或出现异常倒是结束。
在这里插入图片描述

线程的同步

线程安全
(1)问题的提出:
①多个线程执行的不确定性引起执行结果的不稳定。
②多个线程对数据的共享,会造成操作的不完整性,会破坏数据。
(2)例如一个卖票的程序可能会出现重票或错票的问题。出现了线程安全的问题。
(3)问题出现的原因:当某个线程操作车票的过程中,尚未操作完成时,其他线程也加入进来,也操作车票。
(4)如何解决:当一个线程在操作票的时候,其他线程不能参与进来,直到这个线程操作完后,其他线程才可以开始操作。
(5)在java中我们通过同步机制解决线程的安全问题。
①同步代码块:
synchronized(同步监视器){
//需要被同步的代码。
}
说明:
–操作共享数据的代码,即为需要被同步的代码。–>不能包含多了,也不能包含少了。
–共享数据:多个线程共同操作的变量。比如:售票系统中的票。
–同步监视器:俗称:锁。任何一个对象都可以充当锁。
要求:多个线程必须要共用同一把锁。
–好处:同步的方式,解决了线程的安全问题。
–局限性:操作同步代码时只能由一个线程参与,其它线程等待。相当于时一个单线程的过程,效率低。
–实现Runnable的线程可以考虑用this表示锁,继承Thread的慎用this,可以用类.class。

②同步方法:
如果操作的共享数据的代码完整的声明再一个方法中,我们不妨将此方法生名成同步的。(在方法名前加synchronized关键字修饰)
总结 :
–同步方法仍然涉及到同步监视器,只是不需要我们显式的声明。
–非静态的同步方法,同步监视器为:this
静态的同步方法,同步监视器为:当前类本身。

死锁

(1)不同的线程分别占用多方西药的同步资源不放弃,都在等待对方放弃自己需要的同步资源,就形成了线程的死锁。
(2)说明
①出现死锁后,不会出现异常,不会出现提示,只是所有的线程都处于阻塞状态,无法继续。
②我们使用同步时,要避免出现死锁。

Lock

(1)面试题:synchronized与Lock的区别
①相同:二者都可以解决线程的安全问题。
②不同:synchronized机制在执行完相应的同步代码后,自动的释放同步监视器。Lock需要手动的启动同步(lock()方法),同时结束时也需要手动的实现(unlocl()方法)
(2)优先使用顺序:
Lock–>同步代码块(已经进入了方法体,分配了相应的资源)–>同步方法(在方法体外)

线程的通信

(1)涉及到通信的三个方法:
①wait():一旦执行此方法,当前线程就进入阻塞状态,并释放同步监视器。
②notify():一旦执行完此方法就会唤醒被wait()的一个线程。如果多个线程被wait(),就会唤醒优先级高的那个。
③notifyAll():一旦执行此方法就会唤醒被wait的所有线程。
(2)说明:
①wait()、notify()、notifyAll()三个方法需要使用在同步代码块或同步方法中,
②这三个方法的调用者必须是同步代码块或同步方法中的同步监视器,否则会出现异常。
③wait()、notify()、notifyAll()这三个方法都是定义java.lang.Object类中。
(3)面试题:sleep()和wait()的异同
相同点:一旦执行方法,都可以使得当前的线程进入阻塞。
不同点:
①两个方法的声明位置的不同:sleep()声明在Thread类中。wait()声明在wait()类中。
②调用的要求不同:sleep()在任何场景下都可以使用。wait()方法只可以在同步代码块或同步方法中使用。
③关于是否释放同步监视器:sleep()方法不释放同步监视器。wait()方法释放同步监视器。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值