关闭

java多线程的思考

98人阅读 评论(0) 收藏 举报

----------- android培训java培训、java学习型技术博客、期待与您交流! ------------

    之前的学习中,一直是在解决单线程的问题,学完了多线程,更觉计算机技术的美妙,线程是操作系统的概念,也称为轻量级进程,是cpu的基本使用单元,由线程ID,程序计数器,寄存器和堆栈组成,多个线程可以共享代码段,数据段等等资源;传统的进程就是单线程,它们都独享数据段等资源,可称为重量级进程。一个线程包括5种状态,即新建状态:通过new关键字建立;就绪状态:线程调用start()等待cpu分配执行权;运行状态:一旦获取执行权就运行线程内部定义的run()方法,实现其功能;阻塞状态:线程在运行过程中需要等待输入输出操作,或调用了wait(),sleep()即进入临时等待,将执行权让给其它线程;死亡状态:线程执行完即结束生命周期。
    java提供两种方法实现多线程,第一种方法:继承Thread类,Thread类已经具备运行多线程所需的资源,只需复写该类的run()方法,把线程将要实现功能的代码放入其中,创建线程并调用start()方法启动线程,即可与其它线程交替使用cpu资源;代码如下:
class MyThread extends Thread{
      private String name;
      MyThread(String name){
      this.name = name;
      } 
      public void run(){
        for(int i=0;i<9;i++){
           System.out.println(i);
        }
      }
}
class MyThreadDemo{
      MyThread mt = new MyThread("newThread");
      mt.start();
}
第二种方法:实现Runnble接口,Runnble接口只有一个方法run(),实现接口时必须自己定义该方法(复写该方法),如果运行通过实现该接口的多线程,则需要借助Thread类,因为Runnble接口没有提供支持多线程的方法,必须借助Thread类的框架,通过该类的构造函数public Thread(Runnble target)来实现;代码如下:
class MyRunnbleThread implements Runnble{
     public void run(){
           for(int i=0;i<10;i++){
           System.out.println(i); 
           }
     }
}
class MyRunnbleThreadDemo{
     MyRunnbleThread mr = new Thread(new MyRunnbleThread);
     mr.start();
}
     在多线程中经常会遇到资源共享的问题,假设两个线程同时访问一个数据区,一个读数据,一个写数据,如果一个线程在读数据前另一个线程修改了数据,则读数据线程读到的就不是原始数据而是修改过的数据,这样就产生错误,安全问题就产生了,事实上多线程主要就是解决安全问题,为了解决此问题,java中采用了代码同步的方法,即为共享数据加锁,当一个线程访问数据时,拒绝另一个线程同时访问,知道数据空闲,在设计多线程模式中,解决线程冲突都是才用synchronized关键字实现,保证在一段时间内只能有一个线程访问这段代码,实现方式为同步函数或同步代码块,下面已实际应用中的单例设计模式来分析:
class Single{
    private Single(){}
    private static Single s=null;
    private Static getInstanse(){
       if(s=null){
         synchronized(Single.class){
            if(s=null)//线程1,线程2
               s=new Single();
            return s;
         }  
    }
}
因为该类不能创建对象,只能通过getInstanse()获取已经创建的唯一对象,当多个线程使用该方法时,线程1执行到第二个if处cpu切换到线程2,线程2执行到此处也停止,此时线程1重新获取资格继续执行创建一个对象,当线程2也重新获取资格后不再判断,再次创建了一个对象,这样,与单例设计的初衷就相违背,整个程序的执行都将受到影响,若将代码(if(s=null)s=new Single();return s;)封装起来就会避免安全隐患的发生。
    同时要注意,synchronized(Single.class)这个所必须要被一个对象持有,可以是Object,this,.class,但具体用那个,得看需求,像上面这个代码只需保证是一个唯一的对象即可,若同一块数据区,在不同的代码中被使用,必须要用同一把所对这两块代码进行加锁,即使用同一个对象,另外在使用锁机制时,稍有不慎就会发生死锁现象,看下面代码示例:
class Test implement Runnable{
   private boolean flag;
   Test(boolean flag){
      this.flag = flag;
   }
   public void run(){
      if(flag){
         synchronized(locka){
            System.out.println("if locka");
            synchronized(lockb){
                System.out.println("else lockb"); 
            }
         }
     else{
          synchronized(lockb){
            System.out.println("if lockb");
            synchronized(locka){
                System.out.println("else locka"); 
            }
     }
      }
   }
}
上例中,两把锁互相调用都在等对方释放,就会产生死锁问题,所以在实际开发中必须分析清楚那些是共享数据,并找到正确的锁进行同步。
     java中还定义了几个方法用于控制线程的执行顺序:wait(),notify(),notifyAll(), 这些方法可用于线程间通讯,由于任何对象都可作为监视器对象,所以任何对象都可以调用这些方法,但这些方法只能用在被锁控制的代码块或方法中。这些方法又可称为线程的等待唤醒机制,当一个线程只想到某处需要将cpu执行权转让给它人时,调用wait()方法,适当的时候对方会调用notify()方法将其唤醒,当再次获取cpu执行权后继续执行,保证了数据的安全性。
     综上所属,多线程技术是java中最绚丽的技术,也是最难以琢磨的技术,在实际开发中需重点关注,稍有不慎,将有严重后果。所以在写代码之前要详细分析,找出关键因素,理清思路,开发才会更轻松。

----------------------- android培训java培训、java学习型技术博客、期待与您交流! ----------------------

详情请查看:http://edu.csdn.net/heima


 

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:3265次
    • 积分:123
    • 等级:
    • 排名:千里之外
    • 原创:10篇
    • 转载:0篇
    • 译文:0篇
    • 评论:0条
    文章存档