E通信公司面试题------Java相关(原创)

一.Java中的实现多线程的方法

     1、继承Thread(java.lang.Thread)

         通过编写线程类继承Thread类并重写Thread类中的run()方法实现线程,当线程对象被运行时候将会自动执行run方法中的实体内容,从而开辟一个单独的线程并运行起来。

         如:public class ThreadSimple extends Thread{

                  public ThreadSimple()

                  {

                        //constructor

                   }

                  public void run()

                  {

                        //run code entity

                  }

         }

         线程实例使用,直接创建对象并调用start()方法即可运行线程。

         new ThreadSimple().start();

         当执行start方法时候,将会自动运行run方法,但是执行start方法时候只做了一件事,就是将线程转化为可执行状态,然后等待操作系统进行调度并运行,因此无法保证线程能立即启动。在JAVA中,Thread类实现了Runnable接口,因此run方法是通过实现接口Runnable中的抽象方法。

         2、直接实现Runnable多线程接口(java.lang.Runnable)

         线程接口Runnable中只有一个抽象方法run,通过实现Runnable接口中的方法的类即可创建出有多线程特征的对象,但该对象并无法使其启动线程,需要作为参数并借助Thread的构造方法构造创建对象并调用start方法对线程进行启动。

         如:public class RunnablSimple implements Runnable{

                  public RunnableSimple()

                  {

                         //constructor

                  }

                  public void run(){

                        //run code entity

               }

      }

      实现类型的对象使用:

      RunnableSimple rs = new RunnableSimple();

      new Thread(rs).start();

      由此可见,以上两种方法都是通过Threadstart来启动线程的,实际上所有的线程操作都是封装在Thread这个类中,由Thread对象调用各种接口来控制线程。  

      J2ME中线程中主要方法:

      void setPriority(int newPriority),设置线程优先级,在操作系统中线程的调度是不确定性的,可以通过该方法设置相应线程的优先级别。

      static void sleep(long millis) ,线程中静态方法,用于让线程进入休眠状态,执行该方法将会让线程在指定时间millis毫秒内休眠。

      void start(),使现在进入可执行状态。

      void run() ,线程执行主体。

      void join(),等待该线程终止。

      boolean isAlive(),用于判断线程是否出于Alive状态。

      static void yield() ,尽量让其他线程先执行。

二. Java中多线程的互斥

在Java语言中,引入了“对象互斥锁”的概念(又称为监视器、管程)来实现不同线程对共享数据操作的同步。“对象互斥锁”阻止多个线程同时访问同一个条件变量。
在Java语言中,有两种方法可以实现“对象互斥锁”:
1. 用关键字volatile来声明一个共享数据(变量);
2. 用关键字synchronized来声明一个操作共享数据的方法或一段代码。

   小结

1. 实现线程有两种方法:
  -----实现Ruannable接口

  -----继承Thread类
2. 当新线程被启动时,Java运行系统调用该线程的run()方法,它是Thread的核心。
3. 线程有四个状态:创建、可运行、不可运行、死亡。
4. 在applet中通常在其start()方法中创建线程,在stop()方法中终止线程。

三.java中是否有内存泄露(答案:有!)

在Java中,内存的分配是由程序完成的,而内存的释放是有GC完成的。释放对象的根本原则就是该对象不再被引用。了更好理解GC的工作原理,我们可以将对象考虑为有向图的顶点,将引用关系考虑为图的有向边,有向边从引用者指向被引对象。另外,每个线程对象可以作为一个图的起始顶点,例如大多程序从main进程开始执行,那么该图就是以main进程顶点开始的一棵根树。在这个有向图中,根顶点可达的对象都是有效对象,GC将不回收这些对象。如果某个对象 (连通子图)与这个根顶点不可达(注意,该图为有向图),那么我们认为这个(这些)对象不再被引用,可以被GC回收。以下,我们举一个例子说明如何用有向图表示内存管理。对于程序的每一个时刻,我们都有一个有向图表示JVM的内存分配情况。以下右图,就是左边程序运行到第6行的示意图。


              图1

下面,我们就可以描述什么是内存泄漏。在Java中,内存泄漏就是存在一些被分配的对象,这些对象有下面两个特点,首先,这些对象是可达的,即在有向图 中,存在通路可以与其相连;其次,这些对象是无用的,即程序以后不会再使用这些对象。如果对象满足这两个条件,这些对象就可以判定为Java中的内存泄 漏,这些对象不会被GC所回收,然而它却占用内存。

            图2

      因此,通过以上分析,我们知道在Java中也有内存泄漏,但范围比C++要小一些。因为Java从语言上保证,任何对象都是可达的,所有的不可达对象都由GC管理。

      下面给出了一个简单的内存泄露的例子。在这个例子中,我们循环申请Object对象,并将所申请的对象放入一个Vector中,如果我们仅仅释放引 用本身,那么Vector仍然引用该对象,所以这个对象对GC来说是不可回收的。因此,如果对象加入到Vector后,还必须从Vector中删除,最简 单的方法就是将Vector对象设置为null。

       Vector v=new Vector(10);
for (int i=1;i<100; i++)
{
Object o=new Object();
v.add(o);
o=null;
}


//此时,所有的Object对象都没有被释放,因为变量v引用这些对象。


posted @ 2011-10-08 18:27  lxmanutd  阅读(460)  评论(0编辑  收藏  举报