• 热门专题

JAVA中的线程机制(一)

作者:Cindere_liuqiqi  发布日期:2013-08-08 09:41:14
Tag标签:JAVA  线程机制  
  •    所谓的线程就是程序的执行线路。平时我们所写的程序几乎都是单线程的,即程序的执行路径只有一个。但是,在许多应用中单线程是不足以满足我们的要求的。比如:mp3中的功能,如果用单线程去实现,只能播完歌曲之后再显示歌词或者其他,显然不行,我们要求的是边播放歌曲边滚动歌词。这就要用到了我们的多线程,以达到多个功能并发执行。

       在我们平时的程序运行时,主要自启动了两个线程:

       ◆main主线程,调用main方法,执行main方法

       ◆GC线程:垃圾回收机制,主要用于main线程运行时运行,回收程序之中产生的垃圾

      一:线程的构造

       1:继承自Thread的线程类  线程名称  = new 继承自Thread的线程类();-->创建了一个继承自Thread的线程类

       2:Thread 线程名称  = new Thread (实现了Runnable接口的线程类);-->创建一个已经实现了Runnable接口的线程类 www.it165.net

      二:如何写多线程?

     1:继承自Thread类,重写run方法,然后调用Thread的start方法启动这个新线程


    public class TestThread { 
        public static void main(String[] args) { 
            MyThread m = new MyThread();//创建自己定义的线程对象 
            m.start();//启动这个线程对象用start 
            //m.run();相当于方法的调用,并没有开启新线程 
            for(int i =0;i<10;i++){ 
                System.out.println("main-->"+(i+1)); 
            } 
        } 
    } 
    class MyThread extends Thread{//单独定义一个类,继承自Thread类,重写run方法,实现多线程 
        @Override
        public void run() { 
            for(int i =0;i<10;i++){ 
                System.out.println("run-->"+(i+1)); 
            } 
        } 
    }

    结果:

     

    main-->1
    run-->1
    main-->2
    run-->2
    main-->3
    run-->3
    main-->4
    run-->4
    main-->5
    run-->5
    main-->6
    run-->6
    main-->7
    run-->7
    main-->8
    run-->8
    main-->9
    run-->9
    main-->10
    run-->10 
     
    

       结果分析:从结果中可以发现,每次运行这个程序,结果可能不唯一,这是因为程序的执行需要CPU参与, 谁得到了执行权,谁的线程可以运行。main线程和自己创建的线程之间交替进行,也可以说是一种乱序执行,这就是我们所说的多线程之间的乱序执行,那单线程怎么执行的呢?

       单线程也就是我们平时所编写的普通程序,如下:


    public class TestThread { 
        public static void main(String[] args) { 
            MyThread m = new MyThread();//创建自己定义的线程对象 
            //m.start();//启动这个线程对象用start 
            m.run();//相当于方法的调用,并没有开启新线程,仍是单线程 
            for(int i =0;i<10;i++){ 
                System.out.println("main-->"+(i+1)); 
            } 
        } 
    } 
    class MyThread extends Thread{//单独定义一个类,继承自Thread类,重写run方法,实现多线程 
        @Override
        public void run() { 
            for(int i =0;i<10;i++){ 
                System.out.println("run-->"+(i+1)); 
            } 
        } 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 
    } 
     
    

    结果:

     

    run-->1
    run-->2
    run-->3
    run-->4
    run-->5
    run-->6
    run-->7
    run-->8
    run-->9
    run-->10
    main-->1
    main-->2
    main-->3
    main-->4
    main-->5
    main-->6
    main-->7
    main-->8
    main-->9
    main-->10 
     
    

      结果分析:细心的会发现,这个程序只和上边的那个程序有一句之差,而仅仅是这一句之差,让他变成了单线程,这个程序无论执行多少次,结果只有这一个,这就说明:单线程内部顺序执行
     

      2:实现Runnable接口,实现接口中的run方法,创建对象,作为Thread构造的参数,调用thread的start方法启动一个新线程。


    public class MyRunnable { 
        public static void main(String[] args) { 
            MyRun m = new MyRun();//创建实现Runnable接口线程的对象 
            Thread th = new Thread(m);//作为参数传递给线程 
            th.start();//线程的启动     
            for(int i = 0;i<100;i++){ 
                System.out.println("main-->"+(i+1)); 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          
            } 
        } 
    } 
    class MyRun implements Runnable{//线程的第二种创建方法,实现Runnable接口 
        @Override
        public void run() { 
            for(int i = 0;i<100;i++){ 
                System.out.println("run-->"+(i+1)); 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          
            } 
        } 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  
    } 
    

       结果:结果仍然同第一种创建线程的乱序结果(因为是乱序,结果不唯一,可自行试试)

      三:线程的常用方法

       1:start():启动一个新线程,如“线程.start()”这样使用

       2:run():创建线程时,要重写的方法,也是线程启动后运行的方法

       3:Thread.currentThread():获得当前线程

       4:setName(String name):设置线程名称,也可以在创建实现Runnable接口的类对象的参数中传递。

       5:getName():获得线程名称,主线程的名字默认为main,其余线程的默认名字形式为:Thread-0,Thread-1,Thread-2...


    public class MyRunnable { 
        public static void main(String[] args) { 
            MyRun m = new MyRun();//创建实现Runnable接口线程的对象 
            Thread th = new Thread(m);//作为参数传递给线程 
            th.start();//线程的启动  
            th.setName("天津");//给线程命名 
            Thread.currentThread().setName("哈尔滨");//给当前线程main命名 
            for(int i = 0;i<100;i++){ 
                System.out.println(Thread.currentThread().getName()+"-->"+(i+1)); 
                                                                                                                                                                                                                                                                        
            } 
        } 
    } 
    class MyRun implements Runnable{//线程的第二种创建方法,实现Runnable接口 
        @Override
        public void run() { 
            for(int i = 0;i<100;i++){ 
                System.out.println(Thread.currentThread().getName()+"-->"+(i+1)); 
                                                                                                                                                                                                                                                                        
            } 
        } 
                                                                                                                                                                                                                                                                
    } 
     
    

    结果:图中的结果只是截取的,这里要说明的是以上5个方法的使用。任然是乱序执行。

     

    2345678 天津-->77
    哈尔滨-->90
    天津-->78
    哈尔滨-->91
    天津-->79
    哈尔滨-->92
    天津-->80
    哈尔滨-->93 
     
    

       6:getPriority()setPriority():得到和设置线程的优先级。优先级范围:1-10。默认为5。优先级也就是谁的优先级高谁就有更大的可能性运行,所以低优先级的线程并不是不执行,只是没有那么大的机会被执行。在资源不足的情况下有所体现。

     

    public class TestPerority { 
        public static void main(String[] args) { 
            Run m = new Run(); 
                                                                                                                                                                                                                                        
            Thread th1 = new Thread(m); 
            th1.setPriority(10);//设置线程1 的优先级为10 
            th1.start(); 
                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                        
            Thread th2 = new Thread(m); 
            th2.setPriority(1);//设置线程2 的优先级为1 
            th2.start(); 
                                                                                                                                                                                                                                        
        } 
    } 
    class Run implements Runnable{ 
        @Override
        public void run() { 
            for(int i = 0;i<1000;i++){//设置的大一点,看出的效果会大一点 
                System.out.println(Thread.currentThread().getName()+"-->"+(i+1)); 
                                                                                                                                                                                                                                            
            } 
        } 
                                                                                                                                                                                                                                    
    } 
     
    

       结果:可以从结果中看出线程0的优先级高,当他执行到83时,线程1才执行到73。结果仍为乱序。

     

    Thread-0-->83
    Thread-1-->73
    Thread-0-->84
    Thread-1-->74
    Thread-0-->85
    Thread-1-->75 
     
    

       7:sleep():让线程休眠(停止运行)一段时间

     

    public class TestSleep { 
        public static void main(String[] args) { 
            MySleep m = new MySleep(); 
            Thread th = new Thread(m); 
            th.start(); 
                                                                                                                                                                                    
        } 
    } 
    class MySleep implements Runnable { 
        @Override
        public void run() { 
            for (int i = 0; i < 100; i++) { 
                try { 
                Thread.sleep(1000);//让线程停止1秒输出一个,停止1秒输出一个 
            } catch (InterruptedException e) { 
                e.printStackTrace(); 
            } 
                System.out.println(Thread.currentThread().getName() + "-->"
                        + (i + 1)); 
            } 
        } 
    } 
     
    

       执行效果:线程每隔1秒输出一个数,直到输出到100为止。

       8:join():当线程A运行的时候,若线程Bjoin() 进来的话,则暂停A的执行,先执行B,直到B执行结束之后,才继续开始A的执行。


    public class Testjoin { 
        public static void main(String[] args) { 
            MyJoin m = new MyJoin(); 
            Thread th = new Thread(m); 
            th.start(); 
            try { 
                //在main中把th添加进来,只有th执行完毕之后才开始执行main 
                th.join(); 
            } catch (InterruptedException e) { 
                e.printStackTrace(); 
            } 
                                                                                                                                                                       
            for(int i = 0;i<100;i++){ 
                System.out.println(Thread.currentThread().getName()+"-->"+(i+1)); 
                                                                                                                                                                           
            } 
        } 
    } 
    class MyJoin implements Runnable{ 
        @Override
        public void run() { 
            for(int i = 0;i<100;i++){ 
                System.out.println(Thread.currentThread().getName()+"-->"+(i+1)); 
                                                                                                                                                                           
            } 
        } 
                                                                                                                                                                   
    } 
     
    

     结果:

     

    Thread-0-->1
    。。。。。。 
    Thread-0-->97
    Thread-0-->98
    Thread-0-->99
    Thread-0-->100
    main-->1
    main-->2
    main-->3
    main-->4
    main-->5
    。。。。。。 
    main-->100 
     
    

       结果分析:这个程序如果去掉try-catch块中的内容,执行效果和第二个大问题中的第一点一样,应为乱序执行,而加入了join方法之后导致,自己创建的线程先执行,执行结束后才执行main线程。

        9:yield():让位,我把执行权先让出来,大家抢,谁抢到了谁执行,抢不过我,就我执行。


    public class TestYeild { 
        public static void main(String[] args) { 
            MyYeild m = new MyYeild(); 
            Thread th = new Thread(m); 
            th.start();     
            for(int i = 0;i<1000;i++){ 
                System.out.println(Thread.currentThread().getName()+"-->"+(i+1)); 
                                                                                             
            } 
        } 
    } 
    class MyYeild implements Runnable{ 
        @Override
        public void run() { 
            for(int i = 0;i<1000;i++){ 
                System.out.println("让你一下"); 
                //让你一下,你抢得过我你就执行,否则还是我执行 
                Thread.yield(); 
                System.out.println(Thread.currentThread().getName()+"-->"+(i+1)); 
                                                                                             
            } 
        } 
                                                                                     
    } 
     
    

     结果:图中结果为截取的。

     

    main-->958
    Thread-0-->633
    让你一下 
    main-->959
    main-->960
    main-->961
    main-->962
    main-->963
    main-->964
    main-->965
    main-->966
    main-->967
    main-->968
    main-->969
    main-->970
    main-->971
    main-->972
    main-->973
    Thread-0-->634
    让你一下 
    Thread-0-->635 
     
    

       结果分析:线程让位了一下,导致程序结果中的一段如图所示,说明在某一时刻,main线程抢过了自己创建线程的执行权。

       线程还有许多应用,我们明天继续哈...


About IT165 - 广告服务 - 隐私声明 - 版权申明 - 免责条款 - 网站地图 - 网友投稿 - 联系方式
本站内容来自于互联网,仅供用于网络技术学习,学习中请遵循相关法律法规