黑马程序员-----多线程小结

---------------------- <ahref="http://www.itheima.com"target="blank">ASP.Net+Unity开发</a>、<ahref="http://www.itheima.com"target="blank">.Net培训</a>、期待与您交流! ----------------------


概念:

Java是少数的几种支持多线程语言之一。大多数程序设计语言只能运行单独的一个程序块,无法同时运行不同的多个程序块,而Java中的多线程机制可以拟补这个缺憾,它可以让不同的程序块同时运行,这样可以让程序运行更为顺畅,性能更高,同时也可以达到多任务的处理目的。

谈起线程,现得了解进程概念,进程是一次动态的执行过程,他需经历代码加载、代码执行、以及代码执行完毕的过程。多进程的操作系统可同时运行多个进程(程序),例如:Windows操作系统就可在任务管理器中对进程进行查看(如下图),由于CPU具备分时机制,所以每个进程都可循环获得自己的CPU使用时间段,由于CPU执行速度非常快,使得好像所有进程在“同一时间“进行。


而多线程是实现并发机制的一种手段,线程是比进程还要小的执行单位,线程是在进程的基础上进行的进一步划分。所谓多线程是指一个进程在执行过程中可以产生更多的程序单元,这些更小单元称之为线程。


Java中实现线程:

      在Java中要想实现多线程操作有两种方法:

一、继承Thread

二、实现Runnable接口


继承Thread类:

Thread类是java.lang包中定义的,一个类只要继承了Thread类并覆写其中run()方法,此类就可以称之为多线程的实现类,例如以下代码:


package ClassPackage;

//继承Thread实现多线程

 

class ThreadTestextends Thread{  //继承Thread 多线程的实现类

    privateint sum=10;

    publicvoid run()

    {

       for(;sum>0;sum--)   

       System.out.println("sum="+sum);

    }

}

 

publicclass Test28 {

    publicstatic void main(String args[]){

       //创建两个线程,并启动

       ThreadTest t1=new ThreadTest();

       ThreadTest t2=new ThreadTest();

       t1.start();

       t2.start();

    }

}


运行结果:



     从运行结果中我们会发现,两个线程的确都启动了,但是他们的系统资源(sum)确是相互独立的,诺想将其资源共享可将共享资源定义为静态类型(static)类型,或者让其实现Runnable接口完成对共享资源的访问,并且由于Java中每个类定义时只能继承一个父类,若让其继承Thread类来实现多线程,则必定会受到单继承局限的影响。


实现Runnable接口:

Runnable接口中只定义了一个方法:public void run()

所以实现Runnable接口只需实现此方法即可,例如将上述代码进行修改后:


package ClassPackage;

//实现Runnable接口 实现多线程

 

class RunnableTestimplements Runnable{  //实现Runnable接口 

    private int sum=10;

    public void run()

    {

       for(;sum>0;sum--)   

       System.out.println(Thread.currentThread().getName()+" sum="+sum);

    }

}

 

public class Test29 {

    public static void main(String args[]){

       //创建两个线程共享RunnableTest对象的资源,并启动

       RunnableTest t=new RunnableTest();

       Threadt1=newThread(t);

       Threadt2=newThread(t);

       t1.start();

       t2.start();

    }

}


运行结果:



细心的朋友可能已经发现怎么还是有重复值呢?

其实上面的程序的确已经实现了资源的共享,但是之所以出现重复值,正是线程中存在的一个必须注意的问题,即线程的同步问题。 


同步与死锁:
      
出现以上问题的原因是:当一个线程正准备对共享资源进行操作时,忽然失去了CPU执行权,而另一个线程这时进入获得执行权对共享资源进行操作,紧接着又失去执行权,因此出现以上情况,类似这种情况都归根于对共享资源操作的安全问题。


对于以上问题,Java提供两种方法来解决:

一、同步代码块(对以上程序进行了更改,就是为了避免资源安全问题,在此不再细说,感兴趣的朋友可自行更改一遍查看原因):


package ClassPackage;

//实现Runnable接口 实现多线程

 

class RunnableTestimplements Runnable{  //实现Runnable接口 

    privateint sum=100;

    publicvoid run()

    {

      

           for(;;)      

              synchronized(this){

                  if(sum>0)

                     System.out.println(Thread.currentThread().getName()+" sum="+sum--);

                  else break;

       }

    }

}

 

publicclass Test29 {

    publicstatic void main(String args[]){

       //创建两个线程共享RunnableTest对象的资源,并启动

       RunnableTest t=new RunnableTest();

       Thread t1=new Thread(t);

       Thread t2=new Thread(t);

       t1.start();

       t2.start();

    }

}


二、同步函数:


package ClassPackage;

//实现Runnable接口 实现多线程

 

class RunnableTest implements Runnable{  //实现Runnable接口 

    private int sum=100;

    public void run()

    {

      

           for(;;)      

           {

              show();

           }

    }

    public synchronized void show()

    {

       if(sum>0)

           System.out.println(Thread.currentThread().getName()+" sum="+sum--);

    }

}

 

public class Test29 {

    public static void main(String args[]){

       //创建两个线程共享RunnableTest对象的资源,并启动

       RunnableTest t=new RunnableTest();

       Thread t1=new Thread(t);

       Thread t2=new Thread(t);

       t1.start();

       t2.start();

    }

}


加入同步后运行结果:




锁:


上图中this就一个锁,那么我们究竟该如何理解锁的概念呢?


      锁,我们可以简单的将其看作为一把钥匙,而同步则就是门,只有获得了钥匙的人(线程)才能进入门中,并且钥匙只有一把,只能当此时拿着钥匙的人(线程)放弃所有权,其他人(线程)才可进入其中。

何时放弃所有权,即:同步代码块或同步函数执行完成时。


同步函数默认锁为:this

静态同步函数默认锁:类名.class  (该方法所在类的字节码对象,因为静态方法直接由类调用,无本类实例化对象)



(多线程扩展)单例设计模式:


懒汉式:实例的延迟加在,存在问题,当多线程访问时会出现安全问题(共享资源),加入同步来解决,同步代码块和 同步方法 都可,但会降低代码效率,可用双重“if“加快效率,代码如下:


class Single{  //懒汉式(延迟加载)单例设计模式

    private static Single s=null;

    private Single(){};

    public static Single getSingle()

    {

       if(s==null)

       {

           synchronized(Single.class)

           {

              if(s==null)

                  s=new Single();

           }

       }

       return s;

    }

}


饿汉式(多线程访问时,不存在安全问题):


class Single02{

    private static final Single02 s2=new Single02();

    private Single02(){}

    public static Single02getSingle02(){

       returns2;

    }

   

}


死锁:同步中嵌套同步,使用的锁却不同时,可能会产生死锁状态。

实现个简单的死锁状态,代码如下:


package ClassPackage;

//设计出多线程死锁状态

 

class  Deadlock implements Runnable{

    private boolean flag;

    public Deadlock(boolean flag){

       this.flag=flag;

    }

   

    public void run(){ //实现Runnable接口 run()方法

      

       if(flag){ //t1线程进入,并获取lock1

           synchronized(Lock.lock1){

              System.out.println("t1手持 lock1  --->t2索要 lock2 ");

              synchronized(Lock.lock2){

                  System.out.println("t1获得 lock2");

              }

           }

       }else{//t2线程进入,并获得lock2

           synchronized(Lock.lock2){

              System.out.println("t2手持 lock2 --->t1索要lock1");

              synchronized(Lock.lock1){

                  System.out.println("t2获得 lock1");

              }

           }

       }

    }

}

 

class Lock{  //此类专门用于创建两把锁

    static Lock lock1=new Lock(); //1

    static Lock lock2=new Lock(); //2

}

 

public class Test27 {

    public static void main(String args[])

    {

       //创建两个以Deadlock类为共享资源的线程

       Thread t1=new Thread(new Deadlock(true));

       Thread t2=new Thread(new Deadlock(false));

       //启动线程

       t1.start();

       t2.start();

    }

}


和谐状态(未产生死锁):



死锁状态:




所谓死锁,可以比喻为有两个人,每人只有一支筷子,两人都想吃饭桌上的菜,然而A对B说:“把你的筷子给我,我要吃饭“,而B同时对A说:“把你的筷子给我,我也要吃饭”,因此,两人互不相让,产生死锁,相互等待对方让出筷子。而和谐状态则是一人先让出筷子,让另一人吃饭,一定时间后另一人再让出筷子,如此相互交换,就不会出现程序跑死状态。


最后奉献多线程中的经典例题一道(生产者与消费者)链接:

生产者与消费者(线程同步与死锁、等待与唤醒)
http://bbs.itheima.com/thread-109994-1-1.html
(出处: 黑马程序员IT技术论坛)


---------------------- <ahref="http://www.itheima.com"target="blank">ASP.Net+Unity开发</a>、<ahref="http://www.itheima.com"target="blank">.Net培训</a>、期待与您交流! ----------------------



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值