JAVA线程的创建与启动

JAVA线程的创建与启动

 (2007-09-13 02:21:52)

转载

标签: 

IT/科技

 

IT/科技

 

IT/科技

 

IT/科技

 

IT/科技

 

水之后

 

java线程

 

编程

分类: JAVA-初级

一、进程与线程的区别:
    一个进程可以包括多个线程,每个进程都需要操作系统为其分配独立的内存地址空间,同一进程的所有线程在同一块地址空间中工作。

 

二、JAVA线程的运行机制:
    在JAVA虚拟机进程中,执行程序代码的任务是由线程完成的,每个线程都有一个独立的程序计数器和方法调用栈(method invocation stack)。程序计数器也称PC寄存器,当线程执行一个方法时,程序计数器指向方法区中的下一条要执行的字节码指令。方法调用栈是用来跟踪线程运行中一系列的方法调用过程,栈中的元素称为栈帧。每个线程调用一个方法的时候,就会向方法栈压入一个新帧,帧用来存储方法的参数、局部变量和运算过程中的临时数据。栈帧分为三部分:局部变量区、操作数栈和栈数据区。
    当JAVA命令启动一个JAVA 虚拟机进程时,JAVA虚拟机都会创建一个主线程,该线程从程序的入口main()方法开始执行。线程的运行过程例子:
    public class Sample
    {
        private int a;//实例变量

        public int method()
        {
            int b=0;//局部变量
            a++;
            b=a;
            return b;
        }

        public static void main(String args[])
        {
            Sample s=null;//局部变量
            int a=0;//局部变量

            s=new Sample;
            a=s.method;
            System.out.println(a);
        }
    }
    程序从main()入口,当它执行到method()方法的a++操作时,主程序能根据method()方法的栈帧的栈数据区中的有关信息,正确地定位到堆区的Sample对象的实例变量a,并把它的值加1。当meithod()方法执行完毕后,它的栈帧就会从方法栈中弹出,它的局部变量b结束生命周期。main()方法的栈帧就会成为当前帧,主线程继续执行main()方法。


三、线程的创建和启动
    创建线程有两种方式:(1)扩展java.lang.Thread类;(2)实现Runnable接口。
    Thread类主要有两个方法:run()——包含线程运行时所执行的代码;start()——用于启动线程。
    1、线程运行过程的例子:
    package extendth;
    public viod Machine extends Thread
    {
        public void run()//下面大括号里面的两行代码是machine进程时执行的代码
        {
             for(int a=0;a<50;a++)
             System.out.println(a);
        }

        public static void main(String args[])
        {
        Machine machie=new Machine();
        machie.start();//启动machine进程
        }
    }
    当运行java extendth.Machine命令时,java虚拟机首先创建并启动主线程,执行main()方法,main()方法创建一个Machine对象,然后调用它的start()方法启动Machine进程。Machine线程的任务是执行它的run()方法。

    2、主程序与用户自定义的线程并发运行的例子:
    package allrun;
    public class Machine extends Thread
    {
        public void run()
        {
            for(int a=0;a<50;a++)
            {
                System.out.println(currentThread().getName()+":"+a);
                try
                {
                    sleep(100);//给其他线程运行的机会
                }catch(InterruptedException e)
                    {
                    throw new RuntimeException(e);
                    }
            }
        }
        public static void main(String args[])
        {
            Machine machine1 = new Machine();//创建第一个Machine对象
            Machine machine2 = new Machine();//创建第二个Machine对象
            machine1.start();//启动第一个Machine线程
            machine2.start();//启动第二个Machine线程
            machine1.run();//主程序执行第一个Machine对象的run()方法
        }
    }
    上面的例子Machine类的main()方法创建并启动了两个Machine线程,main()方法接着调用第一个Machine对象的run方法。在java虚拟机中有三个线程并发执行的Machine对象的run()方法。在三个线程中各自的方法栈都有代表run()方法的栈帧,在这个帧中存放了局部变量a,可见每个线程都有自己的局部变量a,他们都分别从0增加到50。
    运行结果:
    main:0
    Thread-0:0
    Thread-1:0
    main:1
    Thread-0:1
    Thread-1:1
    ……
    main:49
    Thread-0:49
    Thread-1:49

    3、多个线程共享一个对象的实例变量
    package sharever;
    public class Machine extends Thread
    {
        private int a=0;//实例变量
        public void run()
        {
            for(int a=0;a<50;a++)//使用Machine对象的实例变量a
            {
                System.out.println(currentThread().getName()+":"+a);
                try
                {
                    sleep(100);
                }catch(InterruptedException e)
                {
                    throw new RuntimeException(e);
                }
            }
        }
        public static void main(String args[])
        {
            Machine machine=new Machine;
            machine.start();
            machine.run()
        }
    }
    运行以上程序,主线程和Machine线程都会执行Machine对象的run()方法,都会操纵同一个实例变量a,这两个线程轮流给变量a增加1。
    运行结果:
    main:0
    Thread-0:0
    main:1
    Thread-0:2
    ……
    main:48
    Thread-0:49

    4、不要随便覆盖Thread类的start()方法
    因为start方法是启动一个线程,覆盖的时候可能启动的是被覆盖的线程,而不是本身这个线程。假如一定要覆盖start()方法,那么应该先调用super.start()方法。下面例子的Machine类的start()方法首先调用Thread父类start()方法,确保Machine线程被启动,接着统计被启动的Machine线程的数目,并打印该数目。
    package correctstart;
    public class Machine extends Thread
    {
        private int a=0;
        private static int count=0;//统计被启动的Machine线程的数目
        public void start()
        {
            super.start();
            System.out.println(currentThread().getName()+":第"+(++count)+"个Machine进程启动");//这行代码由主线程执行
        }
        public void run()
        {
            for(int a=0;a<50;a++)//使用Machine对象的实例变量a
            {
                System.out.println(currentThread().getName()+":"+a);
                try
                {
                    sleep(100);
                }catch(InterruptedException e)
                {
                    throw new RuntimeException(e);
                }
            }
        }
        public static void main(String args[])
        {
            Machine machine=new Machine;
            machine.start();
            machine.run()
        }
    }
        public static void main(String args[])
        {
            Machine machine1 = new Machine();
            Machine machine2 = new Machine();
            machine1.start();
            machine2.start();
            machine1.run();
        }
    }

    5、实现Runnable接口
    一个类不能继承多个类,因此一旦一个类继承了Thread类就不能继承其他的类,为了解决这个问题,java提供了java.lang.Runnable接口,它有一个run()方法。
    package runimpl;
    public class Machine implements Runnable
    {
        private int a=0;
        public void run()
        {
            for(int a=0;a<50;a++)
            {
                System.out.println(currentThread().getName()+":"+a);
                try
                {
                    sleep(100);
                }catch(InterruptedException e)
                {
                    throw new RuntimeException(e);
                }
            }
        }
        public static void main(String args[])
        {
            Machine machine=new Machine();
            Thread t1=new Thread(machine);
            Thread t2=new Thread(machine);
            t1.start();
            t2.start()
        }
    }
    在这个例子中,主线程创建了t1和t2两个线程对象,启动t1和t2线程将执行machine变量所引起的Machine对象的run()方法。t1和t2共享同一个machine对象,因此在执行run()方法时将操纵同一个实例变量a。
    运行结果:
    Thread-0:0
    Thread-1:0
    Thread-0:1
    Thread-1:2
    ……
    Thread-0:47
    Thread-1:48
    Thread-0:49
    将以上的main()方法做如下修改,t1和t2线程分别执行machine1和machine2变量所引起的Machine对象的run()方法,因此操纵的是不同的变量a。
    public static void main(String args[])
        {
            Machine machine1=new Machine();
            Machine machine2=new Machine();
            Thread t1=new Thread(machine);
            Thread t2=new Thread(machine);
            t1.start();
            t2.start()
        }
    运行结果:
    Thread-0:0
    Thread-1:0
    ……
    Thread-0:49
    Thread-1:49

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值