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();
由此可见,以上两种方法都是通过Thread的start来启动线程的,实际上所有的线程操作都是封装在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); |
//此时,所有的Object对象都没有被释放,因为变量v引用这些对象。