版权声明:本文为博主林炳文Evankaka原创文章,转载请注明出处http://blog.csdn.net/evankaka

目录(?)[+]

林炳文Evankaka原创作品。转载请注明出处http://blog.csdn.net/evankaka

写在前面的话:此文只能说是Java多线程的一个入门,其实Java里头线程完全可以写一本书了,但是如果最基本的你都学掌握好,又怎么能更上一个台阶呢?如果你觉得此文很简单,那推荐你看看Java并发包的的线程池(Java并发编程与技术内幕:线程池深入理解),或者看这个专栏:Java并发编程与技术内幕。你将会对Java里头的高并发场景下的线程有更加深刻的理解。

目录(?)[-]

  1. 一扩展javalangThread类
  2. 二实现javalangRunnable接口
  3. 三Thread和Runnable的区别
  4. 四线程状态转换
  5. 五线程调度
  6. 六常用函数说明
    1. 使用方式
    2. 为什么要用join方法
  7. 七常见线程名词解释
  8. 八线程同步
  9. 九线程数据传递

本文主要讲了java中多线程的使用方法、线程同步、线程数据传递、线程状态及相应的一些线程函数用法、概述等。在这之前,首先让我们来了解下在操作系统中进程和线程的区别:

; i < 5; i++) {

  • System.out.println(name + "运行  :  " + i);
  • try {
  • sleep((int) Math.random() * 10);
  • } catch (InterruptedException e) {
  • e.printStackTrace();
  • }
  • }
  • }
  • }
  • public class Main {
  • public static void main(String[] args) {
  • Thread1 mTh1=new Thread1("A");
  • Thread1 mTh2=new Thread1("B");
  • mTh1.start();
  • mTh2.start();
  • }
  • }
  • 输出:

    A运行  :  0
    B运行  :  0
    A运行  :  1
    A运行  :  2
    A运行  :  3
    A运行  :  4
    B运行  :  1
    B运行  :  2
    B运行  :  3
    B运行  :  4

    再运行一下:

    A运行  :  0
    B运行  :  0
    B运行  :  1
    B运行  :  2
    B运行  :  3
    B运行  :  4
    A运行  :  1
    A运行  :  2
    A运行  :  3
    A运行  :  4

    说明:
    程序启动运行main时候,java虚拟机启动一个进程,主线程main在main()调用时候被创建。随着调用MitiSay的两个对象的start方法,另外两个线程也启动了,这样,整个应用就在多线程下运行。
     
    注意:start()方法的调用后并不是立即执行多线程代码,而是使得该线程变为可运行态(Runnable),什么时候运行是由操作系统决定的。
    从程序运行的结果可以发现,多线程程序是乱序执行。因此,只有乱序执行的代码才有必要设计为多线程。
    Thread.sleep()方法调用目的是不让当前线程独自霸占该进程所获取的CPU资源,以留出一定时间给其他线程执行的机会。
    实际上所有的多线程代码执行顺序都是不确定的,每次执行的结果都是随机的。

    但是start方法重复调用的话,会出现; i < 5; i++) {

  • System.out.println(name + "运行  :  " + i);
  • try {
  • Thread.sleep((int) Math.random() * 10);
  • } catch (InterruptedException e) {
  • e.printStackTrace();
  • }
  • }
  • }
  • }
  • public class Main {
  • public static void main(String[] args) {
  • new Thread(new Thread2("C")).start();
  • new Thread(new Thread2("D")).start();
  • }
  • }
  • 输出:

    C运行  :  0
    D运行  :  0
    D运行  :  1
    C运行  :  1
    D运行  :  2
    C运行  :  2
    D运行  :  3
    C运行  :  3
    D运行  :  4
    C运行  :  4

    说明:
    Thread2类通过实现Runnable接口,使得该类有了多线程类的特征。run()方法是多线程程序的一个约定。所有的多线程代码都在run方法里面。Thread类实际上也是实现了Runnable接口的类。
    在启动的多线程的时候,需要先通过Thread类的构造方法Thread(Runnable target) 构造出对象,然后调用Thread对象的start()方法来运行多线程代码。
    实际上所有的多线程代码都是通过运行Thread的start()方法来运行的。因此,不管是扩展Thread类还是实现Runnable接口来实现多线程,最终还是通过Thread的对象的API来控制线程的,熟悉Thread类的API是进行多线程编程的基础。

    三、Thread和Runnable的区别

    如果一个类继承Thread,则不适合资源共享。但是如果实现了Runable接口的话,则很容易的实现资源共享。

    总结:

    实现Runnable接口比继承Thread类所具有的优势:

    1):适合多个相同的程序代码的线程去处理同一个资源

    2):可以避免java中的单继承的限制

    3):增加程序的健壮性,代码可以被多个线程共享,代码和数据独立

    4):线程池只能放入实现Runable或callable类线程,不能直接放入继承Thread的类

    ; i < 5; i++) {

  • System.out.println("子线程"+name + "运行 : " + i);
  • try {
  • sleep((int) Math.random() * 10);
  • } catch (InterruptedException e) {
  • e.printStackTrace();
  • }
  • }
  • System.out.println(Thread.currentThread().getName() + " 线程运行结束!");
  • }
  • }
  • public class Main {
  • public static void main(String[] args) {
  • System.out.println(Thread.currentThread().getName()+"主线程运行开始!");
  • Thread1 mTh1=new Thread1("A");
  • Thread1 mTh2=new Thread1("B");
  • mTh1.start();
  • mTh2.start();
  • System.out.println(Thread.currentThread().getName()+ "主线程运行结束!");
  • }
  • }