多线程基础部分小结

1.1线程的概念:

     
         在多线程程序中,一个线程其实就是一条独立的执行的线索。java中的线程有两方面的含义:一是一条独立的执行线索,二是java.lang.Thread类或其子类的对象。

1.2自定义线程:

         方法一:继承 Thread 类,则该类对象便具有了线程的能力。采用此方式需要重写run()方法,run中的代码就是把要被该线程执行的代码。

  代码:

                                 

class MyThread extends Thread{
    public void run(){
         //线程所要执行任务的代码
      }
}
          方法二:实现Runnable 接口,重写run()方法,run中的代码就是把要被该线程执行的代码。

  代码:

class MyRunnable implements Rinnable{
     public void run(){
        //线程所要执行任务的代码   
     }

}
注意:直接调用run()方法并不产生新的执行线索(新线程)
两种方式的比较:

(1)继承Thread类的方式简单,单由于java单一继承的原则,继承了该类就不能继承其他类。其实很多情况下只是希望自己的类具有线程的能力,扮演线程的角色,而自己还需要继承其他的类。

(2)实现Runnable接口,既不影响继承其他类,也不影响实现其他接口,并且使的实现了Runnable接口的类具有了线程的能力,灵活性更好。

其实开发一个线程的关键就是给线程指定其启动后要执行的任务代码,即写在run()中的代码。

1.3创建线程对象

       


方式1:对于继承Thread的类来说,类自身的对象就是线程对象,所以直接创建自身对象即可:
      

Thread thread =  new MyThread();

方式2:对于实现Runnable接口的类来说,其自身的对象并不是一个线程,只是在该类中实现的run()方法指出了线程需要完成的任务。然而,若想得到一个线程,必须创建Thread类或其子类对象,可以使用Thread类的特殊的构造方法:

Runnable r = new MyRunnable();
Thread thread = new Thread( r );
实现了Runnable 接口的类的对象只是指出了线程需要完成的任务,其本身并不是线程对象。实现了Runnable 接口的类的对象可以被同时传递给多个线程对象。

1.4 启动线程

      当线程对象创建完成后,其实还是一个普通的对象,并没有称为一条独立的执行线索。。要想成为独立的执行线索,必须启动线程。

若要启动一个线程,只需要调用线程对象的start()方法即可。注意:线程在其生命周期只能被启动一次。

同时使用多个线程时:java中对于线程启动后的唯一保障就是:“ 每一个线程都将启动,每一个线程都将执行结束”;但是谁会先执行谁会后执行,并没有保障。也就说,就算一个线程在另一个线程之前启动,也不能保障该线程会先执行完毕。

1.5 线程的状态

线程的生命周期一般会经历5个状态:新建,准备,运行,等待/阻塞,死亡。

新建状态:当一个线程对象创建后,其bain处于新建状态。在这种状态下,线程对象还只是一个普通的对象,不可能被线程调度程序调度。

准备状态:处在新建状态下的线程对象调用了start()方法之后,就会进入准备状态。在这种状态下,其随时都有可能被线程调度程序调度,获取cpu执行时间而执行。同时可能有多个线程处于准备状态,等待被调度执行,要注意的是:线程一旦进入准备状态,就不可能在回到新建状态。

运行状态:一旦处于准备状态的线程获取了cpu时间,就进入运行状态。在运行状态下,随时可能被调度程序调度回准备状态。另外,线程在执行过程中,由于需要等待某些必要的条件,或运行了特定的方法,可能会进入等待/阻塞状态。

等待/阻塞状态:位于该状态下的线程由于某些原因而不能继续执行,其原因有多种情况:睡眠、阻塞、挂起、等待某些特定条件的满足等。

         注意:睡眠:是指正在执行的线程调用了sleep方法而进入失眠状态。

                    阻塞:正在运行的线程如果中调用了阻塞的方法,,而正好满足阻塞的情况,就会进入阻塞状态。

                    挂起:正在执行的线程如果调用了suspend方法就会处于挂起状态,直到调用了resume方法才回到准备状态。

                    等待:正在运行的线程由于逻辑逻辑条件不满足,自己调用wait方法进入等待状态,直到收到通知的消息才回到准备状态。

死亡状态:当线程的run方法正确执行完毕或由于发生异常而终止执行时,线程就进入死亡状态。进入死亡状态的线程可以当作普通对象来使用,但是不能再启动,否则会抛异常IllegalThreadStateException。

 
1.6 几个简单的线程调度方法

(1)sleep( long millis) :在线程执行过程中,调用sleep方法可以让线程休眠一段指定的时间,线程醒来后将进入准备状态,并不保证立刻执行。

(2)线程的优先级:setPriority(int newPriority):线程优先级策略:优先级高的线程应该具有更大的获取cpu时间的概率。

(3)线程的让步:使当前运行的线程让出cpu,使得其他线程得以执行。

             线程的让步包括两种方式:

                     方式1:使用yield()方法,调用yield方法使当前正在运行的线程让出cpu,回到准备状态,进而使其他线程有机会进入运行状态。但是:该操作是没有保障的,很可能该线程进入准备状态后又立刻被现车给调度程序调度进入运行状态,因此,yield方法只能保证该线程一定会回到准备状态。

                    方式2:使用join()方法,当一个线程必须等到另一个线程执行完毕后才恢复执行时,使用join方法。

      例如:

public static void main(String[] args){
    //....一些代码

   Thread t = new MyThread();
   t.start();
   //.....
   t.join();
  System.out.println("main线程又开始执行了");

}
当主线程执行到t.join()时,会让出cpu时间,等到 t 线程执行完之后,才会恢复执行,输出:
  main线程又开始执行了
1.7 守护线程:

其实在java中没有单线程程序,就算开发人员只开发了主线程,后台还有很多辅助线线程:线程调度、垃圾回收、内存管理等。这些运行在后台的线程称为守护线程。

只要调用线程对象的setDaemon(boolean on)  如果 on = ture 就可以将该线程对象设置为守护线程。

在java中,非守护线程是保证执行完成的,但是后台守护线程并没有保证。因为java 的运行时环境判断程序执行完毕与否的标准是:”是否所有的非守护线程都执行完毕,如果所有的非守护线程都执行完毕,程序退出。“

1.8 同步线程

              同步方法:同步方法是指synchronized关键字修饰的方法,其与普通方法的不同是进入同步方法的线程将获得同步方法所属对象的锁,一旦对象被锁,其他线程就不能执行被锁对象的任何同步方法,因为线程在执行对象的同步方法时,首先会去获取该对象的锁,如果获取锁失败,则进入对象的锁等待池等待,直到别的线程释放锁,其获得对象锁才能执行同步方法。

synchronized <返回类型> 方法名([参数列表]) [throws <异常序列>]{
      //同步方法代码
}

静态同步方法在执行前,线程需要 获取的是 方法所在的锁,同一个时刻同一个类也只能有一个静态同步方法被访问。

同步方法中调度线程特有的方法:wait() / notify() 都属于Object 类的方法,因此,所有的对象都可以作为资源使用。

         wait() 方法:该方法使得某一线程进入该资源的等待池,使其进入等待状态。直到别的线程调用该资源的notify()或notify All()方法将其唤醒。

         notify() 方法:该方法将唤醒该资源等待池中的某一个线程。具体哪一个随机。

        notifyAll() 方法:该方法将唤醒该资源等待池中的所有线程。

未完,待续。。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值