Java----多线程详解(一)

Java----多线程详解

       多线程是Java基础知识的最后一部分,同样也是Java学习中的一个难点。在学习多线程时,深刻理解它的思想是非常必要的,在有了多线程的思想后,学习多线程的语法和规则就会很容易。

1、多线程简介

       多线程是现代操作系统的发展方向,所以Java肯定是支持多线程的,它具有并发性、执行效率高的特点。多线程是实现并发的一种有效手段,一个进程可以通过运行多个线程来并发地执行多项任务,而多个线程之间的调度执行是由系统来实现的。

       进程是一个执行的程序,多进程的多任务处理的特点是允许计算机同时运行两个或多个程序。它也是一次动态的执行过程,指的是从代码加载、执行到执行结束的一个完整过程。

       线程是比进程小的执行单位,进程的每个小部分都由线程来管理。多线程程序比多进程程序需要更少的“管理费用”。线程共享相同的地址空间并且共同分享同一个进程,这可以使及其节省大量的CPU利用空间,从而能CPU能执行更多的任务。

       下面先看一个使用多线程的示例程序:

public class test{

    ThreadUseExtends tue = newThreadUseExtends();

    public static void main(String[] str) {

        //主线程

        test t = new test();

        t.tue.start();//启动线程

        try {

            Thread.sleep(1000);//主线程挂起1秒

        } catch (Exception e) {

            return;

        }

    }

   

    public void PrintA() {

        for (int i = 0; i < 10; i++) {

            System.out.println(i +"");

        }

    }

   

    public void PrintB() {

        for (int i = 10; i < 20; i++) {

            System.out.println(i +"");

        }

    }

   

    class ThreadUseExtends extends Thread{

        @Override

        public void run() {

            PrintA();

            System.out.println();

            try {

                for (int i = 0; i < 10; i++){

                    sleep(1000);//线程挂起1秒

                   System.out.print("*");

                }

                System.out.println();

                PrintB();

            } catch (Exception e) {

                System.err.println(e);

            }

        }

    }

}

2、如何创建线程

       线程的创建包括主线程的创建、实现Runnable接口创建和继承Thread类的创建。

       1)、主线程的创建

       程序的主线程在程序启动执行时立刻运行,它是所有的线程中最早运行的线程,还是产生其他子线程的线程,同时由于它要执行各种关闭动作,又是最后完成的线程。主线程是在程序启动时自动创建的,但它也是可以由Thread对象控制的。可以通过Thread对象调用currentThread()方法获得一个主线程的引用。获得主线程的引用后,就可以像控制其他线程那样控制主线程了。下面是一个示例:

public static voidmain(String[] str) {

        //获得主线程的引用

        Thread t = Thread.currentThread();

        System.out.println("主线程:" + t);

        t.setName("我的主线程");

        System.out.println("改变名称后:" + t);

        //线程内容

        try {

            for (int i = 0; i < 5; i++) {

                System.out.println(i);

                t.sleep(1000);

            }

        } catch (Exception e) {

            e.printStackTrace();

        }

    }

       t作为语句println()中参数运用时输出的结果,它的顺序为:线程名称、优先级和组的名称。

       2)、实现Runnable接口

       创建一个线程有两个方法:实现Runnable接口;进程Thread类。创建线程最简单的方法就是创建一个实现Runnable接口的类,Runnable抽象了一个执行代码单元。可以通过实现Runnable接口的方法创建每一个对象的线程。实现Runnable接口的类,需要定义一个名为run()的无参数方法。

       实现了Runnable类不需要是Thread的子类就可以运行,只需要实例化一个Thread对象,并把自己的引用当作参数传递给Thread的构造方法即可。

       每个执行线程开始都作为Thread类的一个实例,无论是在哪种创建线程的方法中。首先需要实例化Runnable类:

              MyRunnable r = newMyRunnable();

       然后即可引用Runnable类实例化线程:

              Thread t = new MyRunnable();

       下面是一个通过实现Runnable接口来创建线程的实例:

public class test{

    public static void main(String[] str) {

        //实例化一个线程

        MyThread r = new MyThread();

        Thread t = new Thread(r);

        t.setPriority(5);//设置线程的优先级

        t.start();//对run方法进行调用

        //主程序内容

        try {

            for (int i = 0; i < 10; i++) {

               System.out.println("b");

                Thread.sleep(1000);

            }

        } catch (Exception e) {

        }

        

    }

}

//通过实现Runnable接口创建线程

class MyThread implementsRunnable{

    int i;

    @Override

    public void run() {

        try {

            while (true) {           

               System.out.println("a" + i++);

                Thread.sleep(1000);

                if (i == 10) break;

            }   

        } catch (Exception e) {

        }

    }

}

       请仔细研究这段代码,并多次调试观察打印出来的内容,你会有更好滴理解线程的概念和多线程执行的先后顺序。

       3)、通过继承Thread类创建线程

       Java中创建给管理线程的虚拟CPU是java.lang.Thread类的一个实例。也可以说Thread类的对象就是一个运行代码和使用数据的虚拟CPU。多个Thread对象可以共享代码和数据。继承Thread类创建线程的方法为:创建一个新类来继承Thread类,然后再创建该类的实例。当一个类继承Thread时,它必须重载run()方法,在这里run()方法也是新线程的入口。另外它也必须调用start()方法启动新线程执行。下面是一个实例:

public class test{

    public static void main(String[] str) {

        //实例化一个线程

        MyThread r = new MyThread();

        r.start();//对run()方法进行调用

        r.setPriority(5);//设置优先级

        try {

            for (int i = 0; i < 10; i++) {

               System.err.println("b");

                Thread.sleep(1000);

            }

        }catch (Exception e) {

        }

    }

}

//通过继承Thread创建线程

class MyThread extends  Thread{

    int i;

    @Override

    public void run() {

        try {

            while (true) {           

               System.out.println("a" + i++);

                Thread.sleep(1000);

                if (i == 10) break;

            }   

        } catch (Exception e) {

        }

    }

}

       请将上面的实例跟通过实现Runnable接口创建线程的实例进行对比,通过代码对比和打印内容的对比,你将会发现这两种方法的区别以及各自的优缺点。

       4)、两种方法的比较

       Thread类定义了很多方法可以被它的子类重载,但是只有一个方法必须被重载,那就是run()方法。这个方法也是Runnable接口所必须的。因此如果不需要重载Thread的其他方法,选择实现Runnable接口创建线程的方法是最好的。

       5)、创建多线程

       前面值编写了单线程和双线程,下面来创建多线程。多线程可以为系统的内存分配做一个很好的处理,缓解内存的压力。下面是一个多线程的示例:

public class test{

    public static void main(String[] str) {

        //创建3个线程

        MyThread1 t1 = new MyThread1("第1线程");

        MyThread2 t2 = new MyThread2("第2线程");

        MyThread3 t3 = new MyThread3("第3线程");

        t1.start();

        t2.start();

        t3.start();

    }

}

 

class MyThread1 extendsThread{

    String name;

    public MyThread1(String threadName) {

        name = threadName;

    }

    @Override

    public void run() {

        try {

            for (int i = 0; i < 10; i++) {

                System.out.println(name +":" + i);

                Thread.sleep(1000);

            }

        } catch (Exception e) {

        }

        System.err.println(name + "退出");

    }

}

class MyThread2 extendsThread{

    String name;

    public MyThread2(String threadName) {

        name = threadName;

    }

    @Override

    public void run() {

        try {

            for (int i = 0; i < 10; i++) {

                System.out.println(name +":" + i);

                Thread.sleep(1000);

            }

        } catch (Exception e) {

        }

        System.err.println(name + "退出");

    }

}

class MyThread3 extendsThread{

    String name;

    public MyThread3(String threadName) {

        name = threadName;

    }

    @Override

    public void run() {

        try {

            for (int i = 0; i < 10; i++) {

                System.out.println(name +":" + i);

                Thread.sleep(1000);

            }

        } catch (Exception e) {

        }

        System.err.println(name + "退出");

    }

}

       如果你是个聪明的人,你肯定会问,为什么不只创建一个Thread类MyThread1,然后实例化3个MyThread1开始执行呢?这样做代码不就少了吗?这个问题涉及到线程的优先级和线程的并发执行,现在讲不容易理解,下面我会进行详细的讲解。

       在程序中用到了线程的构造器,在前面的程序中没有直接给出,而是应用的默认构造器。线程中的构造器很多,有如下几种:

       >  Thread()

       >  Thread(Runnable target)

       >  Thread(Runnable target ,String name)

       >  Thread(String name)

       >  Thread(ThreadGroup group ,Runnable target)

       >  Thread(ThreadGroup , group ,Runnable target , String name)

       >  Thread(ThreadGroup group ,String name)

       对线程进行操作时,其运行结果是不确定的,也就是说起运行结果有可能不一样。这就是之前我为什么让大家反复调试查看打印结果的原因。不过可以肯定的是每个线程都将启动,每个线程都运行完成。

 

posted @ 2013-04-03 11:12  坚固66  阅读(165)  评论(0编辑  收藏  举报