黑马程序员-关于java多线程的总结及应用

------- android培训java培训、期待与您交流! ----------

1:多线程

         (1)多线程:

                   进程:正在运行的应用程序

                   线程:应用程序的最小执行单元,执行路径

                   单线程:假如一个应用程序只有一条执行路径,被称为单线程程序

                   多线程:应用程序有多条执行路径

 

                   举例:迅雷下载,jvm的启动(main线程和垃圾回收线程)。

         (2)多线程的实现方案:

                   A:继承Thread类

 

                   B:实现Runnable接口

 

 

                  

                            调用start()和run()方法的区别?

                  直接调用run()方法,是一个普通方法

                 run()调用是一个普通方法的调用,通过线程执行代码的时候,

                  需要启动线程,并调用run()方法。

                  而启动线程和调用run()的方法方法是start()

                       

                            为什么会有第二种方式实现多线程呢?

                 因为java是单继承的,如果一个类已经有父类了,那么,它就无法再继续继承Thread。

               所以,会出现接口的方式。因为一个类继承类的同时还可以实现接口。

示例:

class MeThread extends Thread{

   public void run(){       //继承父类多线程接口需要覆写父类方法

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

      System.out.println(getName()+"**"+i);//继承父类的getName()方法,可以调用省略了this.

      //可以写成System.out.println(Thread.currentThread().getName());

      //currentThread()静态方法,返回当前引用对象,可以直接使用类名调用

   }

}

   }

public classThreadDemo {

public staticvoidmain(String[] args) {

   MeThreadm=newMeThread();

  

   m.start();//调用多线程执行方法

 for(inti=0;i<100;i++){

    System.out.println("-----"+i);

    //可以看出是多线程,在main线程方法向下执行时,遇到了start()启动了另一个线程,此时start()开始执行

    //main继续向下执行,两个线程并列执行,开始争夺虚拟机资源

    

 }

 

}

}

 

         (3)线程随机性原理

                   应用程序是在CPU的高效切换间运行。

         (4)线程的生命周期

                   A:新建新建了线程对象

                   B:就绪具备执行资格,不具备执行权

                   C:运行具备执行资格,具备执行权

                            阻塞 -- 就绪

                            不具备执行资格,不具备执行权  

                   D:死亡线程对象变成垃圾

 

                       

线程状态图解

 

 (5)卖票案例通过两种方式实现。

示例:

Thread实现方式

/*

 * 多线程的应用:多个窗口同时买票的应用

 * */

package ThreadTicket;

 

 class Tickets extends Thread{

    privatestaticinttickets=100;//之所以设置为静态,是因为

   // 每新建一个线程对象,就会有100张票,因此设置为静态共享变量,几个卖票窗口共享这些票

    publicvoidrun(){

    while(true){

       if(tickets>0){

          System.out.println(getName()+"正在卖第"+tickets--+"张票");

       }else{

          break;

       }

    }

    } 

    publicTickets(String name){

       super(name);

       //建立构造方法,在子类构造方法里面调用父类给名字赋值的构造方法this.name=name;

    }

    }

 

public classTicketsDemo{

   public static void main(String [] args){

      Ticketst=newTickets("1号窗口");

      Ticketst1=newTickets("2号窗口");

      Ticketst2=newTickets("3号窗口");

      Ticketst3=newTickets("4号窗口");

      t.start();

      t1.start();

      t2.start();

      t3.start();

   }

}

Runnable实现方式

示例:

/*

 * 第二种实现多线程的方法:实现Runnable接口

   这个接口的出现避免了java只能单继承的局限性

 * */

package RunnableTicket;

/*

 * 使用Runnable接口实现多线程卖票

 * */

class Tickets implements Runnable{

   private int tickets=100;

   public void run(){

      while(true){

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

            //此系统可能出现安全问题,若此时剩了1张票,t1进来走过if语句还未到输出语句,t2此刻抢到了cpu此时票数

            //还是大于0,同理t3,t4可能会进来,那么出现的问题是可能会卖出0,-1,-2张票

           

            if(tickets>0){

                System.out.println(Thread.currentThread().getName()+"正在卖第"+tickets--+"张票");//因为currentThread()是静态方法,可以直接调用,因为返回的是一个对象,可以直接调用其方法

            }else{

                break;

            }

         }

      }

   }

}

public classTicketsDemo {

         public static void main(String [] args){

           Tickets t=new Tickets();

/* m.start(),因为start()Thread的方法,MyRunnable

      Thread没有联系,所以不可以使用.

      Thread的构造方法中有Thread(Runnabletarget) Thread(Runnabletarget, String name)

                       第二个在产生新线程对象的同时可以赋名字

                       此方法接收Runnable对象可以产生新的线程对象

                       所以可以通过建立Thread对象,来调用次方法产生新的线程对象

      */

           Thread t1=newThread(t,"1号窗口");

           Thread t2=newThread(t,"2号窗口");

           Thread t3=newThread(t,"3号窗口");

           Thread t4=newThread(t,"4号窗口");

           t1.start();

           t2.start();

           t3.start();

           t4.start();

         }

}

         (6)卖票出问题了?线程安全问题?

                   A:线程访问的随机性

                   B:线程访问的延迟

         (7)解决方案:同步

                   1)使用synchronized代码块及其原理
public  void output(String name){
synchronized (this) {

for (int i = 0; i < name.length(); i++) {
System.out.print(name.charAt(i)+" ");
}

System.out.println();
}
}
  2)使用synchronized方法
class OutPuter{

public synchronizedvoid output(String name){


for (int i = 0; i < name.length(); i++) {
System.out.print(name.charAt(i)+" ");
}

System.out.println();

}
}

                   锁对象是谁呢?

                            a:同步代码块是任意对象

                            b:普通同步方法是this对象

                            c:静态同步方法是当前类的字节码文件对象

 

                   同步的好处:解决数据安全问题

                   同步的弊端:效率低

 

                   假如针对代码你加了同步,发现还是没有解决问题?

                   A:是不是对所有涉及到的内容都加了锁

                   B:考虑所有的锁对象是不是同一把

         (8)如何判定程序是否会有线程安全问题?

                   A:程序被多个线程访问

                   B:有共享数据

                   C:共享数据被多条语句操作

         (9)单例模式中的线程安全问题

懒汉式的单例模式:可能会出现安全问题

  当一个对象进入判断语句还未进入new对象时另一个对象可能也进入,

  然后就会new两个对象,造成安全问题

  因此需要同步锁机制

  如图

 

 /*class Single  {

         privatestatic Single s=null;

         privateSingle(){}

         publicstatic Single getInstance()

         {

                   if(s==null){

                           

                                               returns=new Single();

                   }

                   returns;

         }

        

}会产生安全问题

*/

//加同步锁之后

class Single{

         privatestatic Single s=null;

         privateSingle(){}//外界无法创建对象

         publicstatic synchronized Single getInstance(){ //因为方法是静态的,此时同步锁的对象是字节码对象 Single.class

                  

                   if(s==null){

                            s=newSingle();

                   }

                   returns;

         }

}

public class SingleDemo {

 

        

         publicstatic void main(String[] args) {

               

         Single s=Single. getInstance();

 

         }

 

}

 ------- android培训java培训、期待与您交流! ----------

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值