多线程总结

作一个简略的总结~

一、多线程的两种方式

  1.通过继承thread类 

    class Thread1 extends Thread{

      public void run(){}

   }

    直接通过new Thread1();  即可通过start()启动线程,调用其run方法

  2.实现runnable接口

   class Thread2 implements Runnable{

    public void run(){}

   }

   启动线程的步骤 :Thread2 t2 = new Thread2();

                                    Thread thread2 = new Thread(t2);

                                      thread2.start();

  一般我们在使用多线程中,通过实现Runnable 接口的方式用的比较多,使用第二种方式有如下好处:

   1)类可以实现多个接口,但是继承只能继承一个

   2)方便资源共享  

  1. class MyThread implements Runnable{  
  2. private int ticket=10;  
  3. public void run(){  
  4. for(int i=0;i<20;i++){  
  5. if(this.ticket>0){  
  6. System.out.println("卖票:ticket"+this.ticket--);  
  7. }  
  8. }  
  9. }  
  10. }  
  11. package org.demo.runnable;  
  12. public class RunnableTicket {  
  13. public static void main(String[] args) {  
  14. MyThread mt=new MyThread();  
  15. new Thread(mt).start();//同一个mt,但是在Thread中就不可以,如果用同一 
  16. new Thread(mt).start();//个实例化对象mt,就会出现异常 
  17. new Thread(mt).start();  
  18. }  
  19. };

上面的例子可以资源共享,共享票数,如果使用第一种方式,创建了3个线程,他对于票数这个变量是独立的,各卖各的票

 二、sleep 登场

  有时候我们将一个线程停顿一下,让它过一会在继续执行,相当于我们玩游戏的暂停,这个时候在run方法中调用一个sleep(time),time表示休眠多久


三、对于一些资源一个线程正在访问,另一个线程中间改变了它,这会导致混乱,这个时候我们用同步 synchronized 解决这个问题

    可以理解为通过同步这个关键字加锁,一个线程访问的时候,其他线程只能等其访问完,这样就不会出现中途被别人修改问题了

   使用synchronized 有几种常见的方法,下面列举两种

   1.加在方法上 

    public synchronized void run(){}

   当一个线程访问该方法的时候,其他线程不能访问,但这不是绝对的,如果通过统一对象生成的线程,比如像上面都是通过t2对象  new thread(t2)产生的线程,可以避免同一对象的线程访问,但是如果是不同对象生成的,这个方式不能解决,通过使用static 可以保证一个类的所有不同对象的避免。


    2.使用在块上

    public  void  run(){

       synchronized(lock){

            // content

      }

   }

四、线程的阻塞

   常用的方式 wait() 和 notify()  、 notifyAll()  ,使用它们必须在synChronized  里面使用,有synchronized 才有锁,这3个方法需要在有锁的情况下使用,需要注意的是,调用完方法后会释放锁。notify() notifyAll() 负责唤醒线程,但是不是说一唤醒线程,它就退出了,还是要等到把自己后面的操作用完,唤醒的线程才起作用。

 比如:

   

  1.            notifyAll();  
  2.         // 注意,notifyAll()以后,并没有退出,而是继续执行直到完成。  
  3.          System.out.printfln("123");



这里调用了notifyAll(),不是马上就去执行唤醒的线程了,还是会执行下面的输出语句。


五、线程的销毁

     线程在完成他的任务后,如果没有其他地方的引用,它会自行销毁。 

    通过interrupt()  stop()  suspend()  可以中断线程,但是都不推荐使用

   stop() 它会解除由线程获取的所有锁定,而且如果对象处于一种不连贯状态,那么其他线程能在那种状态下检查和修改他们。结果很难检查出真正的问题所在。suspend()方法容易发生死锁。调用suspend()方法的时候,目标线程会停下来,但却仍然持有在这之前获得的锁定。此时,其他任何线程都不能访问锁定的资源,除非被“挂起”的线程恢复运行。对任何线程来说,如果它们想恢复目标线程,同时又试图使用任何一个锁定的资源,就会造成死锁。


六、线程的几个概念区别

    1. start()   run()

      start()方法可以启动线程,执行线程的run方法,如果直接调用run方法,则相当于执行了一个普通的方法,按从上到下的顺序执行代码,不存在多线程的概念了

     2. sleep()  wait()

    sleep是线程类(Thread)的方法,导致此线程暂停执行指定时间,给执行机会给其他线程,但是监恐状态依然保持,到时后会自动恢复。调用sleep不会释放对象锁。wait是Object类的方法,对此对象调用wait方法导致本线程放弃对象锁,进入等待此对象的等待锁定池,只有针对此对象发出notify方法(或notifyAll方法)后本线程才进入对象锁定池准备获得对象锁进入运行状态。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值