• 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)

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

     

  • 相关阅读:
    如何解决列表框控件宽度不够的问题
    在windows Forms程序里面实现文件上传
    TFS的一些信息
    百钱百鸡问题
    如何移动SQL SERVER的系统数据库
    数据分页技术
    如何在报表中直接使用数据库中存储的图片
    重新注册MSJetOledb 4.0引擎
    2007 Microsoft Office Servers 已知问题/自述文件
    使用For XML与XSL(XSLT)配套快速输出查询结果到Web页面
  • 原文地址:https://www.cnblogs.com/jiangu66/p/2997501.html
Copyright © 2020-2023  润新知