您的位置:首页 > 编程语言 > Java开发

个人学习总结一Java的多线程

2014-10-21 14:43 169 查看
多线程
一、多线程概述

1、 进程

        是一个正在执行的程序。

        每一个进程执行都有一个执行顺序。该顺序是一个执行路径,或者叫一个控制单元。

2、线程

         就是进程中的一个独立的控制单元。线程在控制着进程的执行。只要进程中有一个线程在执行,进程就不会结束。

        一个进程中至少有一个线程。

3、多线程

        在java虚拟机启动的时候会有一个java.exe的执行程序,也就是一个进程。该进程中至少有一个线程负责java程序的执行。而且这个线程运行的代码存在于main方法中。该线程称之为主线程。JVM启动除了执行一个主线程,还有负责垃圾回收机制的线程。像种在一个进程中有多个线程执行的方式,就叫做多线程。

4、多线程存在的意义

        多线程的出现能让程序产生同时运行效果。可以提高程序执行效率。

         例如:在java.exe进程执行主线程时,如果程序代码特别多,在堆内存中产生了很多对象,而同时对象调用完后,就成了垃圾。如果垃圾过多就有可能是堆内存出现内存不足的现象,只是如果只有一个线程工作的话,程序的执行将会很低效。而如果有另一个线程帮助处理的话,如垃圾回收机制线程来帮助回收垃圾的话,程序的运行将变得更有效率。

5、计算机CPU的运行原理

         我们电脑上有很多的程序在同时进行,就好像cpu在同时处理这所以程序一样。但是,在一个时刻,单核的cpu只能运行一个程序。而我们看到的同时运行效果,只是cpu在多个进程间做着快速切换动作。

         而cpu执行哪个程序,是毫无规律性的。这也是多线程的一个特性:随机性。哪个线程被cpu执行,或者说抢到了cpu的执行权,哪个线程就执行。而cpu不会只执行一个,当执行一个一会后,又会去执行另一个,或者说另一个抢走了cpu的执行权。至于究竟是怎么样执行的,只能由cpu决定。

二、创建线程的方式

        创建线程共有两种方式:继承方式和实现方式(简单的说)。

1、 继承方式

        通过查找java的帮助文档API,我们发现java中已经提供了对线程这类事物的描述的类——Thread类。这第一种方式就是通过继承Thread类,然后复写其run方法的方式来创建线程。

创建步骤:

        a,定义类继承Thread。

        b,复写Thread中的run方法。

             目的:将自定义代码存储在run方法中,让线程运行。

        c,创建定义类的实例对象。相当于创建一个线程。

        d,用该对象调用线程的start方法。该方法的作用是:启动线程,调用run方法。

注:如果对象直接调用run方法,等同于只有一个线程在执行,自定义的线程并没有启动。

覆盖run方法的原因:

        Thread类用于描述线程。该类就定义了一个功能,用于存储线程要执行的代码。该存储功能就run方法。也就是说,Thread类中的run方法,用于存储线程要运行的代码。

2、 实现方式

        使用继承方式有一个弊端,那就是如果该类本来就继承了其他父类,那么就无法通过Thread类来创建线程了。这样就有了第二种创建线程的方式:实现Runnable接口,并复习其中run方法的方式。

创建步骤:

        a,定义类实现Runnable的接口。

        b,覆盖Runnable接口中的run方法。目的也是为了将线程要运行的代码存放在该run方法中。

        c,通过Thread类创建线程对象。

        d,将Runnable接口的子类对象作为实参传递给Thread类的构造方法。

         为什么要将Runnable接口的子类对象传递给Thread的构造函数?

        因为,自定义的run方法所属的对象是Runnable接口的子类对象。所以要让线程去指定对象的run方法,就必须明确该run方法所属对象。

        e,调用Thread类中start方法启动线程。start方法会自动调用Runnable接口子类的run方法。

实现方式好处:避免了单继承的局限性。在定义线程时,建议使用实现方式。

三、两种方式的区别和线程的几种状态

1、两种方式的区别

  区别一:

  a.由于子类重写了Thread类的run(), 当调用start()时, 直接找子类的run()方法

  b.构造函数中传入了Runnable的引用, 成员变量记住了它, start()调用run()方法时内部判断成员变量Runnable是否为空, 不为空则执行Runnable的run()

  区别二:

  a.继承Thread只能是单继承,如果自己定义的线程类已经有了父类,就不能再继承了

  b.实现Runnable接口可以多实现,即使自己定义线程类已经有父类可以实现Runnable接口

  总结:继承Thread的好处是:可以直接使用Thread类中的方法,代码简单

       弊端是:如果已经有了父类,就不能用这种方法

     实现Runnable接口的好处是:即使自己定义的线程类有了父类也没关系,因为有了父类也可以实现接口,而且接口是可以多实现的弊端是:不能直接使用Thread中的方法需要先获取到线程对象后,才能得到Thread的方法,代码复杂
优先使用Runnable 接口 ---- 因为java单继承,如果继承Thread 就不能继承其他类

2、线程的四种状态:
被创建:等待启动,调用start启动。

         运行状态:具有执行资格和执行权。

         临时状态(阻塞):有执行资格,但是没有执行权。

         冻结状态:遇到sleep(time)方法和wait()方法时,失去执行资格和执行权,sleep方法时间到或者调用notify()方法时,获得执行资格,变为临时状态。

         消忙状态:stop()方法,或者run方法结束。  

四.Thread类常用方法

 1.获取名字

  通过getName()方法获取线程对象的名字

 2.设置名字

  通过构造函数可以传入String类型的名字

  通过setName(String)方法可以设置线程对象的名字

 3.获取当前线程对象

  Thread.currentThread(), 主线程也可以获取

 4.休眠

  Thread.sleep(毫秒)

 5.守护

  setDaemon(), 设置一个线程为守护线程, 该线程不会单独执行, 当其他非守护线程都执行结束后, 自动退出

 6.加入

  join(), 当前线程暂停, 等待指定的线程执行结束后, 当前线程再继续

  join(int), 可以等待指定的毫秒之后继续

       sleep 使当前线程睡眠一段时间,睡眠过程中,不释放锁资源

       join 等待目标线程执行结束后,当前线程才能继续执行
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  多线程 java