实现线程有两种方法,继承Thread类或实现Runnable接口,这两种方法都能很好地实现多线程功能。
对于Runnable接口,只要将要实现多线程功能的代码写在RUN方法中,然后在类代码中的任何要运行线程的地方新建一个Thread实例并将实现Runnable接口类的这例作为实参传入Thread对象中,并调用start方法启动线程。
对于继承Thread类,只要将线程代码写在RUN方法中,并在其它类的任何需要该线程的地方直接生成该线程类的实例,并调用start方法启动线程
区别:
1。Runnable适合扩展已有类,使其具有多线程功能,继承Thread适合用于将单独的线程功能封装。Runnable易于访问要扩展类的成员。
2。Runnable只是实现了线程要做的功能,这个类还不算是线程,必须将其传入一个线程类中让其成为线程的一部份,由这个线程类来控制线程的状态。而继承Thread类则能将线程功能实现并由自身子类自由控制。
共同点:
1。无论是哪种方法实现的线程,都能在代码中调用SLEEP方法,只是写法不一。SLEEP是Thread类的静态方法,Runnable接口本身是没有这个方法的。因此,在Runnable中须用Thread.sleep来调用,目的是将执行当前代码的线程睡眠,相当于Thread.currentThread().sleep(),而对于继承Thread的子类,调用sleep方法则自然不过了,也就是说对于Runnable接口或Thread子类的控制所能用的方法是一致的。
2。在RUN中的代码包括函数调用所指向函数代码,在执行过程中是形成一体的,都是该线程代码的一部份,这里的例外是由系统自动调用的函数代码,如:repaint()所调用的paint().
同步:
synchronized关键字能出现在任何可能要做线程同步处理的代码中,不一定是在Thread子类中或Runnable接口中或Run中,它可用于任何一个类的方法,而这个类可能是由线程来调用,因此要做线程同步处理。同时,synchronized也可用于任何需要同步处理的同步代码中,而这个位置是不受任何限制的。
通信:
wati,notify,notifyall是Object类的静态方法,所有的类都会继承该三个方法,它们只能在标有synchronized的代码中使用,都是通知调用该代码的线程完成某一操作。
例子:
import java.applet.*;
import java.awt.*;
public class myapplet extends Applet implements Runnable
{
int count=0;
Thread t;
public void init()
{
t=new Thread(this);
t.start();
}
public void paint(Graphics g)
{
count++;
g.drawString(""+count,10,50);
}
public void run()
{
for (int i = 0; i<20; i++)
{ repaint();
try
{
Thread.sleep(500);
}
catch(Exception e)
{
e.printStackTrace();
}
}
}
}
以上的例子,实现在窗口中循环打印0至19的数字,如果不用线程来实现的话,数字是不能在窗体中显示的,因为循环操作占用CPU大量的时间,而窗体重划的线程得不到时间来重绘窗体。因此,要完成这样的功能须用来线程,并将调用重绘的方法放在RUN方法中,实现多线程,再且,每次的调用都将调用当前线程的代码睡眠0。5秒,Thread.sleep(500)。在init方法中生成一个线程Thread子类,用于操纵线程,实例化线程对象时将当前类的对象传入这个线程对象中,因为当前类实现了run方法,也就是线程要完成的工作。