Java基础之多线程

 更新时间:2018年09月14日 14:35:49   作者:小刀爱编程  
以下是我们Java基础多线程的一些知识点总结,看完以后会觉得多线程也可以这么简单,小编精心推荐,希望能对大家有所帮助

线程中run()和start()的区别:
对于Thread对象来说,当你调用的是start(),线程会被放到等待队列,等待CPU调度,不一定马上执行;无需等待run()方法执行完毕,可以直接执行下面的代码;
而调用的是run()的话,就是当做普通的方法调用,程序还是要顺序执行的;
新建线程的几种方式:
实现Runnable接口;里面实现run()方法;
然后把这个实现了Runnable接口的类就新建为一个Thread t = new Thread(new (实现Runnable接口的类)),调用start()方法即可开始一个线程了。记住,start()只是开启,然后就会返回,继续执行start()下面的语句了。

线程执行器:
我们可以通过不同的线程执行器来实现多线程的执行,有以下几种执行器:

ExecutorService exec = Executors.newCachedThreadPool();

ExecutorService exec = Executors.newFixedThreadPool(5);

ExecutorService exec = Executors.newSingleThreadExecutor();

我们可以对比一下这三者的区别:第一个执行会为每一个任务都创建一个线程,
而第二个则是可以一次性指定要分配多少线程,而第三个则是属于单线程,会一个线程一个线程的依次执行;

休眠:
会使得任务中断一段时间,相当于变相的阻塞了,可以给其他线程制造机会去执行;
但是我们不能通过sleep()来试图控制线程的顺序执行,而是要考虑用同步控制来实现;

让步:
通过使用yield()方法来给线程调度机制一个暗示:你的工作已经完成的差不多了,可以让别的线程使用CPU了,其功能上跟sleep()其实是差不多的。

后台线程:
指在程序运行的时候在后台提供一种通用服务的线程,并且这种线程并不属于程序总共不可或缺的部分,当所有非后台线程结束时,程序终止;由后台线程创建的线程也是后台线程;
在线程调用start()之前,调用setDaemon(true);

实现多线程的另一种方式:
通过继承Thread的方式来实现:而且run()方法是放在构造函数里面的,也就是说,当初始化一个线程的时候,就自动的开启了线程,记得run()方法里面一般都是一个while()循环;

加入一个线程:
一个线程可以在其他线程之上调用join()方法,如果某个线程在另一个线程t上调用t.join();此线程将被挂起,知道目标线程t结束才恢复;
join()方法,你在一个线程中join()了一个线程进来,你就要等待这个线程结束了,才可以把自己这个线程给结束掉;join()的底层实现是wait()方法;

同步:
Synchronzied;可以用在方法上,也可以用到类上面;

显式地使用lock对象
先用Lock lock = new ReentrantLock();建出一个锁对象出来,然后在方法里面,先调用lock.lock();然后try语句里面是方法体,最后记得要在finally里面加上lock.unlock();这样就就相当于解锁了。

区别:
可以看到synchronized lock相比起来,lock似乎要加上一些try/catch语句才可以,但是,这也是好处之一,比起synchronized,可以多出来处理的过程,让用户出现错误的可能性降低;
使用原子类也可以实现资源共享的问题,但是原子类一般很少在常规编程中用到,用于性能调优,然后AtomicInteger,AtomicLong等原子类,使用这些的时候,不需要用到synchronized和lock,但是原子类很少用到,所以我们还是用synchronized和lock。

线程的状态:
新建;就绪;阻塞;死亡;

导致阻塞的几个原因:
1,通过调用sleep()使任务进入休眠状态,

2,通过调用wait()使线程挂起,知道线程得到notify()notifyAll()消息,

3,任务再等待某个输入/输出完成;

4,任务视图在某个对象上调用其同步控制方法,但是对象锁不可用,因为另一个任务已经获取了这个锁;

中断:
这是一个大学问呀。一般的话,我们中断都是用interrupted(),但是,我们现在说了,用Executor执行器可以更好地执行了,所以我们如如何在执行器中中断线程呢?这也很好办,用Executor的shutdownNow(),但是,这又是一个问题了,这只是用来中断所有的线程的,但是我们是想要中断某一个线层那该怎么办呢?这就用到了返回式了,通过submit()来启动任务的时候,我们就能够得到返回的类型Future<?>通过这个去调用calcel()来中断某个线程。具体等一下码,现在还要讨论的还有一个问题,中断的线程是否有一些是无法中断的,判定如下:如果是在sleep()中的线程,那么显然是可以中断的,但是对于正在读取I/O的线程和正在试图获取锁的线程,我们是无法中断的,而中断线程就相当于抛出了一个异常,方便我们关闭掉资源。

线程之间的协作:
当线程同时运行多个任务时,我们可以用锁来同步两个任务的行为,同时也可以用wait()notifyAll()来实现对线程的控制;
wait()就是一种挂起的状态,当你挂起了之后,锁将被释放,把空出来的线程,给别人执行,而等到被调用notify()唤醒之后,又会重新获得之前wait()锁,如果这个时候锁正在被使用的话,就要陷入等待了。

wait()跟sleep()之间的区别:
1,在synchronized中,wait()期间对象锁是释放的;而sleep()锁是不会释放的;

2,可以通过notify(),notifyAll(),或者令时间到期,从wait()中恢复执行;

唤醒的区别:
notify()方法保证的唤醒是指唤醒的是恰当的任务,另外,为了使用notify(),你必须等待相同的条件,而对于notifyAll()来说,是否所有的线程都会被唤醒呢?只有当notifyAll()因某个特定锁被调用时,只有等待这个锁的任务才能被唤醒;

除了wait()和notify(),我们还可以显式地使用lock和Condition对象;
使用互斥并允许任务挂起的基本类是Condition;可以通过在Condition上调用await来挂起一个任务,通过signal()来通知这个任务,唤醒这个任务,或者调用signalAll()来唤醒所有在这个Condition上被其自身挂起的任务;与使用notify()相比,signlAll()是更安全的方式;

Lock lock = new ReentrantLock();

Condition condition = lock.newCondition();

lock.lock();

lock.unlock();

condition.await();

但是我们要知道显式的lock对象,相比起wait(),notify()来说,更加复杂,所以还是建议用回原来的那个wait(),LockCondition只有在更加困难的多线程问题才是必需的;

死锁:
当某一个任务在等待另一个任务的锁释放,而下一个任务又在等待上一个锁的释放,在这样呈链式的循环里面,直到这个链条上的任务又在等待第一个任务释放锁,得到了一个任务之间的相互等待的连续循环;称为死锁;
哲学家就餐问题;经典的死锁问题;
发生死锁的四个满足条件:

1,互斥条件,任务使用的资源中国至少有一个是不能共享的。

2,至少有一个任务它必须持有一个资源把那个正在等待获取另一个被别的任务持有的资源;

3,资源不能被任务抢占;

4,必须要有等待循环;

防止死锁的最容易的方式是破坏第四个条件。

总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对脚本之家的支持。如果你想了解更多相关内容请查看下面相关链接

相关文章

  • Java Selenium实现多窗口切换的示例代码

    Java Selenium实现多窗口切换的示例代码

    这篇文章主要介绍了Java Selenium实现多窗口切换的示例代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-09-09
  • SpringBoot自动装配之@Import深入讲解

    SpringBoot自动装配之@Import深入讲解

    由于最近的项目需求,需要在把配置类导入到容器中,通过查询,使用@Import注解就能实现这个功能,@Import注解能够帮我们吧普通配置类(定义为Bean的类)导入到IOC容器中
    2023-01-01
  • Java中static变量作用和用法详解

    Java中static变量作用和用法详解

    Java 中被 static 修饰的成员称为静态成员或类成员。它属于整个类所有,而不是某个对象所有,即被类的所有对象所共享。静态成员可以使用类名直接访问,也可以使用对象名进行访问.下面我们来详细了解一下吧
    2019-06-06
  • JAVA用for循环打印空心菱形

    JAVA用for循环打印空心菱形

    大家好,本篇文章主要讲的是JAVA用for循环打印空心菱形,感兴趣的同学赶快来看一看吧,对你有帮助的话记得收藏一下
    2022-01-01
  • MyBatis注解式开发映射语句详解

    MyBatis注解式开发映射语句详解

    这几年来注解开发越来越流行,Mybatis也可以使用注解开发方式,这样我们就可以减少编写Mapper映射文件了。我们先围绕一些基本的CRUD来学习,再学习复杂映射多表操作
    2023-02-02
  • Spring Cloud详细讲解zuul集成Eureka流程

    Spring Cloud详细讲解zuul集成Eureka流程

    这篇文章主要介绍了Spring Cloud zuul集成Eureka,Eureka Client中内置一个负载均衡器,用来进行基本的负载均衡,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-06-06
  • Java的NIO与IO的详解及对比

    Java的NIO与IO的详解及对比

    这篇文章主要介绍了Java的NIO与IO的详解及对比的相关资料,需要的朋友可以参考下
    2017-03-03
  • Java数据结构之链表详解

    Java数据结构之链表详解

    本篇文章我们将讲解一种新型的数据结构—链表,链表是一种使用广泛的通用数据结构,它可以用来作为实现栈,队列等数据结构的基础.文中有非常详细的介绍,需要的朋友可以参考下
    2021-05-05
  • IDEA安装详细步骤(多图预警)

    IDEA安装详细步骤(多图预警)

    这篇文章主要介绍了IDEA安装详细步骤(多图预警),本文通过图文并茂的形式给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-04-04
  • Spring中基于XML的AOP配置详解

    Spring中基于XML的AOP配置详解

    这篇文章主要介绍了Spring中基于XML的AOP配置,本文通过图文实例相结合给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-10-10

最新评论