您的位置:首页 > 职场人生

《黑马程序员》 传统创建线程方式回顾

2014-03-27 15:56 309 查看
------- android培训java培训、期待与您交流! ----------
public class TraditionThread {
public static void main(String[] args) {
Thread thread = new Thread();
thread.start();
// 我们直接newThread创建出来的线程,它会去找Thread类里面的run方法
// 我们因为没有代码,所以这个线程的生命就很短,一出来就死亡了

// 其实Thread的内部是这样实现的
/*
* public void run() { if (target != null) { target.run(); } }
* 因为Thread里面run方法内部的代码什么都没有。所以线程开启了就死亡了
*/

/**
* 传统的创建线程的第一种方式: 直接new thread的子类 子类唯一比唯一多的一个功能就是子类可以覆盖父类的代码
*/
// 我们想让我们的线程执行我们自己的代码
// 我们就要创建Thread的子类,然后覆盖父类的run方法。即把要执行的代码写在
// 覆盖的run方法里面
Thread thread2 = new Thread() {
@Override
public void run() {
while (true) {
try {
Thread.sleep(10); // 我们让线程休眠10毫秒
} catch (InterruptedException e) {
e.printStackTrace();
}
// 我们让当前的线程不停的执行一个操作
System.out.println("thread_:"
+ Thread.currentThread().getName() + "...Id:"
+ Thread.currentThread().getId());
// 不停的打印当前线程的名字
// 这样线程会处于很累的状态。我们让线程悠着点。不让它执行的那么快
}
}
};
thread2.start();

/**
* 传统的创建线程的第二种方式: 把线程要执行的任务封装到Runable对象的run方法中。
* 然后将Runnable对象传递给Thread的构造方法。
*
* 现在我们来理解一下为什么会这样? 因为Thread中的run方法中实现的原理是: public void run() { if
* (target != null) { target.run(); } }
* 这样也就是说我们上一个的操作是new了一个Thread的子类并且覆盖了父类里面的 run方法。在运行的时候是这样的,我们直接new
* Thread是没有任何作用的。因为 里面的run方法,只是判断runnable对象是否存在,直接存在,则调用这个ruuable
* 对象的run方法。我们直接new Thread的时候就是调用它里面的run方法里面的代码。 这里什么都没有。而我们在new
* Thread子类的时候,覆盖了Thread中run方法里面的代码 所以就执行我们的代码。
*
*
* 当Thread中的target对象不为空的时候,它就会在Thread的run方法中去执行target的run方法里面的内容。
* 这里的target就是一个Runnable对象。
*
* target赋值是通过init方法进行赋值的。它将传递给init方法的runable对象赋值给了thread里面的成员变量
* target,现在我们就是要看的是在哪里调用的这个方法
*/
Thread thread3 = new Thread(new Runnable() {

@Override
public void run() {
while (true) {
try {
Thread.sleep(10); // 我们让线程休眠10毫秒
} catch (InterruptedException e) {
e.printStackTrace();
}
// 我们让当前的线程不停的执行一个操作
System.out.println("thread_:"
+ Thread.currentThread().getName() + "...Id:"
+ Thread.currentThread().getId());
// 不停的打印当前线程的名字
// 这样线程会处于很累的状态。我们让线程悠着点。不让它执行的那么快
}
}
});
thread3.start();

/**
* 有一个分析题,我们下面的代码,它执行的会是哪个里面的代码
*   我们得出的结论是它会去执行子类里面的代码
*      new Thread(runnable.run){run}.start();
*        创建了一个子类,它的start方法一调用,它就执行了
*        分析如下:
*           在创建这个对象的时候,如果子类覆盖了父类的run方法,就直接执行子类
*           中的run方法,就不会再去找父类了,如果子类中没有覆盖父类中的run方法,
*           它就会去找Thread类中的Runnable,找到Runnable之后,它就会去调用Runnable
*           接口接口实现中的run方法
*/
new Thread(new Runnable() {

@Override
public void run() {
while (true) {
try {
Thread.sleep(10); // 我们让线程休眠10毫秒
} catch (InterruptedException e) {
e.printStackTrace();
}
// 我们让当前的线程不停的执行一个操作
System.out.println("thread_:"
+ Thread.currentThread().getName() + "...Id:"
+ Thread.currentThread().getId());
// 不停的打印当前线程的名字
// 这样线程会处于很累的状态。我们让线程悠着点。不让它执行的那么快
}
}
}) {
public void run() {
while (true) {
try {
Thread.sleep(10); // 我们让线程休眠10毫秒
} catch (InterruptedException e) {
e.printStackTrace();
}
// 我们让当前的线程不停的执行一个操作
System.out.println("thread_:"
+ Thread.currentThread().getName() + "...Id:"
+ Thread.currentThread().getId());
// 不停的打印当前线程的名字
// 这样线程会处于很累的状态。我们让线程悠着点。不让它执行的那么快
}
};
}.start();

// 打印主线程
System.out.println("主线程:__名称:" + Thread.currentThread().getName()
+ "...Id:" + Thread.currentThread().getId());

/**
* 其实传统的两种的方式创建的线程最终起作用的还是Thread类
*   一种是使用了Thread的子类,覆盖了父类中的run方法
*   另外一个是把线程要执行的任务封装在Runnable对象的run方法里面在
*     然后把Runnable对象传递给了Thread类的构造方法。
*  为什么我们在写程序的过程中都是使用的第二种了?
*     这是因为第二种更接近对面向对象的思想。
*       因为我们是把任务封装在了Runnable对象,然后Thread又调用了Runnable这个对象
*         即是Thread这个类在指挥Runnable干事情。
*/
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息