Java中的线程

来源:互联网 发布:excel大批量数据查找 编辑:程序博客网 时间:2024/06/16 23:19

理解线程

这段时间在看《Java并发编程实战》这本书,使自己对Java多线程的理解又加深一些,感觉自己可以总结一下了,本文就讲讲与线程有关的内容吧。我们要使用线程,首先需要理解线程,前短时间我在聊聊操作系统这篇文章中提到了一点关于线程的东西,有兴趣的同学可以读一下。有一点需要理解的就是,我们虽然常说“Java多线程”,但实际上线程这东西是由操作系统提供支持的,它并不是由Java本身提供支持的,所以实际上线程的实现是平台相关的!看过Object类源码的同学应该都能注意到,Object类中实现的控制线程的wait()notify()方法都是被native关键字修饰的本地方法,也表示了这些方法是平台相关的,所以实际上我们通过调用wait(),notify()实现的线程等待唤醒机制是通过使用C语言调用操作系统提供的接口来实现的(个人理解,如有错误还望指正)。操作系统在执行系统调用的时候还涉及到一个用户态与内核态切换的问题,其中包括了程序执行状态的保存和数据的复制,这个过程便消耗一些资源。而且当线程数量很多时,系统的上下文切换时间也会增加,这样过多的线程反而会降低系统的响应速度。其实我认为Java应用只是对操作系统中的线程进行了抽象和封装,这也算是Java能够实现平台无关性的原因之一。

Java中实现线程的方式(三种)

Java是几乎完全面向对象的语言,起初学Java的时候对对象的理解太肤浅,以至于有很多现象不能理解。经过了这么久的学习,感觉自己对对象的理解更加深入。现在就从对象的角度,来谈一下线程。在Java中,每个线程实例就是一个对象实例,这也符合一切皆是对象的思想。所以,如何创建一个线程的问题就变成了如何创建一个对象的问题,我们对这个线程的操纵也就是对这个对象的操纵。如何创建一个对象这个问题我想在Java中应该不算是一个问题了吧!创建对象,当然是通过类来创建,这个类就是Thread类。这也就是创建线程的第一种方法了——继承Thread类。但是这种方式有一点不好就是在Java只允许继承一个类,如果类已经继承了Thread类,就不能再继承其他类了。于是就产生了实现Runnable接口的方式,但是实现了该接口的对象并不是一个线程对象,它只是一个可以被线程执行的对象,如果要启动这个线程,还需要把该对象传递给一个线程对象去执行它,比如通过Thread类的构造方法——public Thread(Runnable r)。那么第三种方式是什么呢,是通过实现Callable接口,这种方式和实现Runnable接口的方式类似,但是Callable中的call()方法可以抛出异常并且可以有返回值

关于线程池

在java.util.concurrent包中提供了一套线程池框架,JDK中的实现当然很棒,Doug Lea的作品自然让人惊叹,但有时候杀鸡焉用宰牛刀。只要弄清楚了基本原理,自己实现一个轻量的线程池也并不是很难。下面就是我自己实现的一个Java线程池,还有很多不完善的地方,大家可以简单参考。线程池的精髓在于持有两个集合,一个任务集合,一个线程集合。线程集合中的线程不断从任务集合中取出任务并执行,执行完毕之后线程并不结束,继续等待执行任务。在我的实现中,任务集合选择了阻塞队列,这样就不需要自己判断队列的状态来让添加任务或取出任务的线程等待或唤醒。那么,使用线程池到底有什么好处呢?第一,线程池避免了不断创建和销毁线程的开销。第二,线程池的使用,避免了程序创建大量的线程从而导致系统上下文切换时间增加的问题。第三,因为每个线程都需要占有一定的内存,当线程数量过多时,可能会导致内存不足,而线程池则避免了该问题。

总结

并发的确是个问题,它导致我们的程序总是出现意想不到的结果,使得程序编写更加复杂,但是并发确实在一定程度上提高了程序的运行效率。只要我们弄懂其中的原理,遵守相应的规则,并发程序便一定会按照我们的想法做事。

2 0