Java基础知识(4)

Java基础知识(四)

   接上篇博客内容《Java基础知识(三)》

   成员变量的继承

   方法可以通过类的继承方式实现继承,成员变量也可以实现继承,成员变量能否被继承取决于它的修饰符。

   (1)public成员变量

   对于public的成员变量,它的任何子类都可以继承它。

 

   (2)protected成员变量

   protected类型的变量,它的子类可以访问,不管该子类与父类是否处于同一个包内。

 

   (3)默认修饰符成员变量

   对于默认修饰符,包外的子类是不能访问它的,包内类可以继承。

 

   (4)private成员变量

   对于private类型的成员变量,任何子类都是不能继承的,它是类私有的。

 

 

    成员变量的隐藏

   子类中定义与父类同名的成员变量。被隐藏的父类成员变量可以通过super关键字访问。

 

   继承与组合

   继承是子类与父类之间的关系,它们是is-a的关系。

   组合是指一个类中除基本类型外还有其他的类的对象作为他的成员,它们是has-a的关系。

 

   组合通常用于在新类中使用已有类的功能,而不是它的接口的情形,也就是把对象作为新类的成员变量,用它来实现所需要的功能。

 

 

   异常

   Java中,所有的异常类都是内置类Throwable的子类。Throwable有两个子类,一个是Exception,一个是Error。

   一个分支是Error,定义了Java运行时的内部错误。

   一个分支是Exception,用于程序中应该捕获的异常。Exception类也有两个分支,一个是RuntimeException,一个是IOException。

   RuntimeException,主要用来描述由于编程产生的错误。

 

 

   线程

   Java中有两种方法创建线程:一种是对Thread类进行派生并覆盖run方法;另一种是通过实现runnable接口创建。

   java.lang.Thread类是一个通用的线程类,由于默认情况下run方法是空的,直接通过Thread类实例化的线程对象不能完成任何事,所以可以通过派生Thread类,并用具体程序代码覆盖Thread类中的run方法,实现具有各种不同功能的线程类。

   Thread创建线程步骤:

   (1)创建一个新的线程类,继承Thread类并覆盖Thread类的run()方法。

class ThreadType extends Thread {
    public void run(){
        ....
    }
}

 

   (2)创建一个线程类的对象,创建方法与一般对象的创建相同,使用关键字new完成。

ThreadType tt = new ThreadType();

 

   (3)启动新线程对象,调用start()方法。

tt.start();

  

   (4)线程自己调用run()方法。

void run();

 

   Java线程并不能按调用顺序执行,而是并行执行的单独代码。

 

   通过实现Runnable接口的方法是创建线程类的第二种方法。Runnable接口提供了run()方法的原型,因此创建新的线程类时,只要实现此接口,即只要特定的程序代码实现Runnable接口中的run()方法,就可完成新线程类的运行。

   Runnable创建线程步骤:

   (1)创建一个实现Runnable接口的类,并且在这个类中重写run()方法

class ThreadType implements Runnable {
    public void run() {
        ...
    }
}

 

   (2)使用关键字new新建一个ThreadType的实例

Runnable rb = new ThreadType();

 

   (3)通过Runnable的实例创建一个线程对象,在创建线程对象时,调用的构造函数是new Thread(ThreadType),它用ThreadType中实现的run()方法作为新线程对象的run()方法。

Thread td = new Thread(rb);

 

   (4)通过调用ThreadType对象的start()方法启动线程运行。

td.start();

 

 

   线程周期

   一个线程有4种状态,任何一个线程都处于这4种状态中的一种。

   (1)创建(new)状态:调用new方法产生一个线程对象后、调用start方法前所处的状态。当线程处于创建状态时,线程对象可以调用start方法进入启动状态,也可以调用stop方法进入停止状态。

   (2)可运行(runnable)状态:当线程对象执行start()方法后,线程就转到可运行状态。进入此状态只是说明线程对象具有了可以运行的条件,但线程并不一定处于运行状态。一个线程是否在运行,除了线程必须处于Runnable状态之外,还取决于优先级和调度。

   (3)不可运行(non Runnable)状态:线程处于不可运行状态是由于线程被挂起或者发生阻塞,如对一个线程调用wait()函数后,它就可能进入阻塞状态;调用线程的notify或notifyAll方法后它才能再次回到可执行状态。

   (4)退出(done)状态:一个线程可以从任何一个状态中调用stop方法进入退出状态。线程一旦进入退出状态就不存在了,不能再返回到其他的状态。如果线程执行完run方法,也会自动进入退出状态。

 

   线程状态转换

   1 线程进入可执行状态

   当以下几种情况发生时,线程进入可执行状态

   (1)其他线程调用notify()或者notifyAll()方法,唤起处于不可执行状态的线程。

   notify仅仅唤醒一个线程并允许它获得锁,notifyAll唤醒所有等待这个对象的线程,并允许它们获得锁。

   (2)线程调用sleep(millis)方法,millis毫秒之后线程会进入可执行状态。

   (3)线程对I/O操作的完成。

 

   2 线程进入不可执行状态

   当以下几种情况发生时,线程进入不可执行状态

   (1)线程自动调用wait()方法,等待某种条件的发生。

   当其他线程调用notify()方法或notifyAll()方法后,处于等待状态的线程获得锁之后才会被唤醒,然后该线程一直等待重新获得对象所才继续运行。

   (2)线程调用sleep()方法进入不可执行状态,在一定时间后会进入可执行状态;

   (3)线程等待I/O操作的完成。

 

   isAlive()方法用来判断一个线程是否存活。当线程处于可执行状态或不可执行状态时,isAlive()方法返回true;当线程处于创建状态或退出状态时,则返回false。

 

   为了解决线程同步问题,Java提供了锁机制实现线程的同步。锁机制的原理是每个线程进入共享代码之前获得锁,否则不能进入共享代码区,并且在退出共享代码之前释放该所,这样就解决了多个线程竞争共享代码的情况,达到线程同步的目的。Java中锁机制的实现方法是共享代码之前加入synchronized关键字。

   在一个类中,用关键字synchronized声明的方法为同步方法。

 

   线程通信

   多线程之间可以通过消息通信,以达到相互协作的目的。Java中线程之间的通信是通过Object类中的wait()、notify()、notifyAll()等几种方法实现的。Java中每个对象内部不仅有一个对象锁,还有一个线程线程等待队列,这个队列用于存放所有等待对象锁的线程。