Java多线程-线程的同步

          Java语言使用多线程实现一个程序中的多个任务同时运行,程序员可以在程序中执行多个线程,每个线程完成一个功能,并与其他线程并发执行,这种机制成为多线程。(并发,事实上在同一个时间点上只有一个线程被执行,只是线程之间的切换比较快,才会产生线程是同时进行的假象。)

          在学习java多线程之前先了解下程序,进程,线程的关系。

          程序是一段静态的代码,它是应用程序执行的蓝本。进程是程序的一次动态执行过程,它对应了从代码加载、执行至执行完毕的一个完整过程,这个过程也是进程本身从产生、发展至消亡的过程。线程是比进程更小的单位,一个进程执行过程中可以产生多个线程,每个线程有自身的产生、存在和消亡的过程,也是一个动态的概念。每个进程都有一段专用的内存区域,而线程间可以共享相同的内存区域(包括代码和数据),并利用这些共享单元来实现数据交换、实时通信与必要的同步操作。 
          每个Java程序都有一个默认的主线程。Java程序总是从主类的main方法开始执行。当JVM加载代码,发现main方法后就启动一个线程,这个线程就称作"主线程",该线程负责执行main方法。在main方法中再创建的线程就是其他线程。如果main方法中没有创建其他线程,那么当main方法返回时JVM就会结束Java应用程序。但如果main方法中创建了其他线程,那么JVM就要在主线程和其他线程之间轮流切换,保证每个线程都有机会使用CPU资源,main方法返回(主线程结束)JVM也不会结束,要一直等到该程序所有线程全部结束才结束Java程序(另外一种情况是:程序中调用了Runtime类的exit方法,并且安全管理器允许退出操作发生。这时JVM也会结束该程序)。
 

          java中要实现多线程,有两种方法:(1)继承Thread类。(2)实现Runable接口。

          对于直接继承Thread的类来说,代码大致框架是:

              public class 类名 extends Thread{

                        public void run(){

                              //编写业务代码

                                  }

                     }

            注:主线程是从main()方法开始运行的,但Thread类的线程对象是从run()方法开始执行的,所以继承Thread类之后,需要重写run()方法,在该方法中实现自己的业务处理。Thread类的start()方法用于启动一个线程对象,线程对象调用start()方法后java虚拟机启动该线程对象,并调用该线程的run()方法执行业务代码。

   

            先看一个简单的例子:

 
    public class Hello extends Thread {
     private String name;
    public Hello(String name) {
        this.name = name;
    }
  
    public void run() {
        for (int i = 0; i < 5; i++) {
            System.out.println(name + "运行     " + i);
        }
    }
  
    public static void main(String[] args) {
        Hello h1=new Hello("A");
        Hello h2=new Hello("B");
        h1.start();
        h2.start();
    }
  
    }

            【运行结果】:

                        A运行     0
                        B运行     0
                        A运行     1
                        B运行     1
                        B运行     2
                        A运行     2
                        A运行     3
                        A运行     4
                        B运行     3
                        B运行     4
           注:因为需要用到CPU的资源,会按照时间片轮流运行,所以每次的结果可能都不一样。

           注意:虽然我们在这里调用的是start()方法,但是实际上调用的还是run()方法的主体。那么我们为什么不直接调用run()方法呢?原因:线程的运行需要本地操作系统的支持。

           对于通过实现Runable接口的方法,大致框架如下:

          public class  类名 implements Runnable{

                    public void run(){

                     //业务处理代码

                   }

           }

          示例如下:

         public class  HelloRunnable  implements Runnable{

 

         private String name;

 

      public HelloRunnable (String name) {

 

        this.name = name;

 

        }

 

        public void run() {

 

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

 

            System.out.println(name + "运行     " + i);

 

        }

 

       }

 

       public static void main(String[] args) {

 

        HelloRunnable h1=new HelloRunnable ("线程A");

 

        Thread demo= new Thread(h1);

 

        HelloRunnable h2=new HelloRunnable ("线程B");

 

        Thread demo1=new Thread(h2);

 

        demo.start();

 

        demo1.start();

 

       }

 

    }
     【运行结果】:
      线程A运行     0
      线程B运行     0
      线程A运行     1
      线程B运行     1
      线程B运行     2
      线程B运行     3
      线程A运行     2
      线程B运行     4
      线程A运行     3
      线程A运行     4
 
   

     Thread和Runnable的区别:

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

     总结一下:

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

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

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

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

 
posted @ 2012-11-02 18:07  学无先后 达者为先  阅读(312)  评论(0编辑  收藏  举报